diff options
1545 files changed, 46026 insertions, 18663 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 77346a4929..1fbdc2652b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -9,7 +9,7 @@ freebsd_task: DEFAULT_TEST_TARGET: prove DEVELOPER: 1 freebsd_instance: - image_family: freebsd-13-2 + image_family: freebsd-13-4 memory: 2G install_script: pkg install -y gettext gmake perl5 diff --git a/.clang-format b/.clang-format index 6408251577..9547fe1b77 100644 --- a/.clang-format +++ b/.clang-format @@ -32,6 +32,9 @@ AlignConsecutiveAssignments: false # double b = 3.14; AlignConsecutiveDeclarations: false +# Align consecutive macro definitions. +AlignConsecutiveMacros: true + # Align escaped newlines as far left as possible # #define A \ # int aaaa; \ @@ -72,6 +75,10 @@ AlwaysBreakAfterReturnType: None BinPackArguments: true BinPackParameters: true +# Add no space around the bit field +# unsigned bf:2; +BitFieldColonSpacing: None + # Attach braces to surrounding context except break before braces on function # definitions. # void foo() @@ -96,6 +103,14 @@ BreakStringLiterals: false # Switch statement body is always indented one level more than case labels. IndentCaseLabels: false +# Indents directives before the hash. Each level uses a single space for +# indentation. +# #if FOO +# # include <foo> +# #endif +IndentPPDirectives: AfterHash +PPIndentWidth: 1 + # Don't indent a function definition or declaration if it is wrapped after the # type IndentWrappedFunctionNames: false @@ -108,11 +123,18 @@ PointerAlignment: Right # x = (int32)y; not x = (int32) y; SpaceAfterCStyleCast: false +# No space is inserted after the logical not operator +SpaceAfterLogicalNot: false + # Insert spaces before and after assignment operators # int a = 5; not int a=5; # a += 42; a+=42; SpaceBeforeAssignmentOperators: true +# Spaces will be removed before case colon. +# case 1: break; not case 1 : break; +SpaceBeforeCaseColon: false + # Put a space before opening parentheses only after control statement keywords. # void f() { # if (true) { @@ -124,6 +146,14 @@ SpaceBeforeParens: ControlStatements # Don't insert spaces inside empty '()' SpaceInEmptyParentheses: false +# No space before first '[' in arrays +# int a[5][5]; not int a [5][5]; +SpaceBeforeSquareBrackets: false + +# No space will be inserted into {} +# while (true) {} not while (true) { } +SpaceInEmptyBlock: false + # The number of spaces before trailing line comments (// - comments). # This does not affect trailing block comments (/* - comments). SpacesBeforeTrailingComments: 1 @@ -169,6 +199,11 @@ ForEachMacros: - 'strmap_for_each_entry' - 'strset_for_each_entry' +# A list of macros that should be interpreted as conditionals instead of as +# function calls. +IfMacros: + - 'if_test' + # The maximum number of consecutive empty lines to keep. MaxEmptyLinesToKeep: 1 @@ -177,13 +212,14 @@ KeepEmptyLinesAtTheStartOfBlocks: false # Penalties # This decides what order things should be done if a line is too long -PenaltyBreakAssignment: 10 -PenaltyBreakBeforeFirstCallParameter: 30 -PenaltyBreakComment: 10 +PenaltyBreakAssignment: 5 +PenaltyBreakBeforeFirstCallParameter: 5 +PenaltyBreakComment: 5 PenaltyBreakFirstLessLess: 0 -PenaltyBreakString: 10 -PenaltyExcessCharacter: 100 -PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyBreakOpenParenthesis: 300 +PenaltyBreakString: 5 +PenaltyExcessCharacter: 10 +PenaltyReturnTypeOnItsOwnLine: 300 # Don't sort #include's SortIncludes: false diff --git a/.github/workflows/check-style.yml b/.github/workflows/check-style.yml new file mode 100644 index 0000000000..c052a5df23 --- /dev/null +++ b/.github/workflows/check-style.yml @@ -0,0 +1,34 @@ +name: check-style + +# Get the repository with all commits to ensure that we can analyze +# all of the commits contributed via the Pull Request. + +on: + pull_request: + types: [opened, synchronize] + +# Avoid unnecessary builds. Unlike the main CI jobs, these are not +# ci-configurable (but could be). +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-style: + env: + CC: clang + jobname: ClangFormat + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - run: ci/install-dependencies.sh + + - name: git clang-format + continue-on-error: true + id: check_out + run: | + ./ci/run-style-check.sh \ + "${{github.event.pull_request.base.sha}}" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 13cc0fe807..808ddc19b8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -113,13 +113,15 @@ jobs: cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v4 - - uses: git-for-windows/setup-git-for-windows-sdk@v1 + - name: setup SDK + shell: powershell + run: ci/install-sdk.ps1 - name: build - shell: bash + shell: powershell env: HOME: ${{runner.workspace}} NO_PERL: 1 - run: . /etc/profile && ci/make-test-artifacts.sh artifacts + run: git-sdk/usr/bin/bash.exe -l -c 'ci/make-test-artifacts.sh artifacts' - name: zip up tracked files run: git archive -o artifacts/tracked.tar.gz HEAD - name: upload tracked files and build artifacts @@ -147,10 +149,12 @@ jobs: - name: extract tracked files and build artifacts shell: bash run: tar xf artifacts.tar.gz && tar xf tracked.tar.gz - - uses: git-for-windows/setup-git-for-windows-sdk@v1 + - name: setup SDK + shell: powershell + run: ci/install-sdk.ps1 - name: test - shell: bash - run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 10 + shell: powershell + run: git-sdk/usr/bin/bash.exe -l -c 'ci/run-test-slice.sh ${{matrix.nr}} 10' - name: print test failures if: failure() && env.FAILED_TEST_ARTIFACTS != '' shell: bash @@ -181,16 +185,12 @@ jobs: repository: 'microsoft/vcpkg' path: 'compat/vcbuild/vcpkg' - name: download vcpkg artifacts - shell: powershell - run: | - $urlbase = "https://dev.azure.com/git/git/_apis/build/builds" - $id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=9&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id - $downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[0].resource.downloadUrl - (New-Object Net.WebClient).DownloadFile($downloadUrl, "compat.zip") - Expand-Archive compat.zip -DestinationPath . -Force - Remove-Item compat.zip + uses: git-for-windows/get-azure-pipelines-artifact@v0 + with: + repository: git/git + definitionId: 9 - name: add msbuild to PATH - uses: microsoft/setup-msbuild@v1 + uses: microsoft/setup-msbuild@v2 - name: copy dlls to root shell: cmd run: compat\vcbuild\vcpkg_copy_dlls.bat release @@ -342,39 +342,42 @@ jobs: - jobname: linux-musl image: alpine distro: alpine-latest + # Supported until 2025-04-02. - jobname: linux32 - image: daald/ubuntu32:xenial - distro: ubuntu32-16.04 + image: i386/ubuntu:focal + distro: ubuntu32-20.04 - jobname: pedantic image: fedora distro: fedora-latest + # A RHEL 8 compatible distro. Supported until 2029-05-31. + - jobname: almalinux-8 + image: almalinux:8 + distro: almalinux-8 + # Supported until 2026-08-31. + - jobname: debian-11 + image: debian:11 + distro: debian-11 env: jobname: ${{matrix.vector.jobname}} distro: ${{matrix.vector.distro}} runs-on: ubuntu-latest container: ${{matrix.vector.image}} steps: - - uses: actions/checkout@v4 - if: matrix.vector.jobname != 'linux32' - - uses: actions/checkout@v1 # cannot be upgraded because Node.js Actions aren't supported in this container + - name: prepare libc6 for actions if: matrix.vector.jobname == 'linux32' + run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6 + - uses: actions/checkout@v4 - run: ci/install-dependencies.sh - run: ci/run-build-and-tests.sh - name: print test failures if: failure() && env.FAILED_TEST_ARTIFACTS != '' run: ci/print-test-failures.sh - name: Upload failed tests' directories - if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname != 'linux32' + if: failure() && env.FAILED_TEST_ARTIFACTS != '' uses: actions/upload-artifact@v4 with: name: failed-tests-${{matrix.vector.jobname}} path: ${{env.FAILED_TEST_ARTIFACTS}} - - name: Upload failed tests' directories - if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname == 'linux32' - uses: actions/upload-artifact@v1 # cannot be upgraded because Node.js Actions aren't supported in this container - with: - name: failed-tests-${{matrix.vector.jobname}} - path: ${{env.FAILED_TEST_ARTIFACTS}} static-analysis: needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' diff --git a/.gitignore b/.gitignore index 8caf3700c2..6687bd6db4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /GIT-PYTHON-VARS /GIT-SCRIPT-DEFINES /GIT-SPATCH-DEFINES +/GIT-TEST-SUITES /GIT-USER-AGENT /GIT-VERSION-FILE /bin-wrappers/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 37b991e080..a1bc92893f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,11 @@ default: timeout: 2h +stages: + - build + - test + - analyze + workflow: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" @@ -9,6 +14,10 @@ workflow: test:linux: image: $image + stage: test + needs: [ ] + tags: + - saas-linux-medium-amd64 variables: CUSTOM_PATH: "/custom" before_script: @@ -25,6 +34,9 @@ test:linux: fi parallel: matrix: + - jobname: linux-old + image: ubuntu:20.04 + CC: gcc - jobname: linux-sha256 image: ubuntu:latest CC: clang @@ -62,6 +74,8 @@ test:linux: test:osx: image: $image + stage: test + needs: [ ] tags: - saas-macos-medium-m1 variables: @@ -95,8 +109,42 @@ test:osx: - t/failed-test-artifacts when: on_failure +build:mingw64: + stage: build + tags: + - saas-windows-medium-amd64 + variables: + NO_PERL: 1 + before_script: + - ./ci/install-sdk.ps1 -directory "git-sdk" + script: + - git-sdk/usr/bin/bash.exe -l -c 'ci/make-test-artifacts.sh artifacts' + artifacts: + paths: + - artifacts + - git-sdk + +test:mingw64: + stage: test + tags: + - saas-windows-medium-amd64 + needs: + - job: "build:mingw64" + artifacts: true + before_script: + - git-sdk/usr/bin/bash.exe -l -c 'tar xf artifacts/artifacts.tar.gz' + - New-Item -Path .git/info -ItemType Directory + - New-Item .git/info/exclude -ItemType File -Value "/git-sdk" + script: + - git-sdk/usr/bin/bash.exe -l -c "ci/run-test-slice.sh $CI_NODE_INDEX $CI_NODE_TOTAL" + after_script: + - git-sdk/usr/bin/bash.exe -l -c 'ci/print-test-failures.sh' + parallel: 10 + test:fuzz-smoke-tests: image: ubuntu:latest + stage: test + needs: [ ] variables: CC: clang before_script: @@ -106,6 +154,8 @@ test:fuzz-smoke-tests: static-analysis: image: ubuntu:22.04 + stage: analyze + needs: [ ] variables: jobname: StaticAnalysis before_script: @@ -116,15 +166,44 @@ static-analysis: check-whitespace: image: ubuntu:latest + stage: analyze + needs: [ ] before_script: - ./ci/install-dependencies.sh + # Since $CI_MERGE_REQUEST_TARGET_BRANCH_SHA is only defined for merged + # pipelines, we fallback to $CI_MERGE_REQUEST_DIFF_BASE_SHA, which should + # be defined in all pipelines. script: - - ./ci/check-whitespace.sh "$CI_MERGE_REQUEST_TARGET_BRANCH_SHA" + - | + R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit + ./ci/check-whitespace.sh "$R" + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + +check-style: + image: ubuntu:latest + stage: analyze + needs: [ ] + allow_failure: true + variables: + CC: clang + jobname: ClangFormat + before_script: + - ./ci/install-dependencies.sh + # Since $CI_MERGE_REQUEST_TARGET_BRANCH_SHA is only defined for merged + # pipelines, we fallback to $CI_MERGE_REQUEST_DIFF_BASE_SHA, which should + # be defined in all pipelines. + script: + - | + R=${CI_MERGE_REQUEST_TARGET_BRANCH_SHA-${CI_MERGE_REQUEST_DIFF_BASE_SHA:?}} || exit + ./ci/run-style-check.sh "$R" rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' documentation: image: ubuntu:latest + stage: analyze + needs: [ ] variables: jobname: Documentation before_script: @@ -257,6 +257,7 @@ Stefan Naewe <stefan.naewe@gmail.com> <stefan.naewe@googlemail.com> Stefan Sperling <stsp@elego.de> <stsp@stsp.name> Å tÄ›pán NÄ›mec <stepnem@gmail.com> <stepan.nemec@gmail.com> Stephen Boyd <bebarino@gmail.com> <sboyd@codeaurora.org> +Stephen P. Smith <ishchis2@gmail.com> <ischis2@cox.net> Steven Drake <sdrake@xnet.co.nz> <sdrake@ihug.co.nz> Steven Grimm <koreth@midwinter.com> <sgrimm@sgrimm-mbp.local> Steven Grimm <koreth@midwinter.com> koreth@midwinter.com diff --git a/Documentation/BreakingChanges.txt b/Documentation/BreakingChanges.txt index 0532bfcf7f..27acff86db 100644 --- a/Documentation/BreakingChanges.txt +++ b/Documentation/BreakingChanges.txt @@ -59,10 +59,29 @@ over time. If circumstances change, an earlier decision to deprecate or change something may need to be revisited from time to time. So do not take items on this list to mean "it is settled, do not waste our time bringing it up again". +== Procedure + +Discussing the desire to make breaking changes, declaring that breaking +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. + +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. + + == 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. +is no planned release date for this breaking version yet. The early +adopter configuration used for changes for this release is `feature.git3`. 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 @@ -115,6 +134,26 @@ info/grafts as outdated, 2014-03-05) and will be removed. + Cf. <20140304174806.GA11561@sigill.intra.peff.net>. +* The git-pack-redundant(1) command can be used to remove redundant pack files. + The subcommand is unusably slow and the reason why nobody reports it as a + performance bug is suspected to be the absence of users. We have nominated + the command for removal and have started to emit a user-visible warning in + c3b58472be (pack-redundant: gauge the usage before proposing its removal, + 2020-08-25) whenever the command is executed. ++ +So far there was a single complaint about somebody still using the command, but +that complaint did not cause us to reverse course. On the contrary, we have +doubled down on the deprecation and starting with 4406522b76 (pack-redundant: +escalate deprecation warning to an error, 2023-03-23), the command dies unless +the user passes the `--i-still-use-this` option. ++ +There have not been any subsequent complaints, so this command will finally be +removed. ++ +Cf. <xmqq1rjuz6n3.fsf_-_@gitster.c.googlers.com>, + <CAKvOHKAFXQwt4D8yUCCkf_TQL79mYaJ=KAKhtpDNTvHJFuX1NA@mail.gmail.com>, + <20230323204047.GA9290@coredump.intra.peff.net>, + == Superseded features that will not be deprecated Some features have gained newer replacements that aim to improve the design in diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 1d92b2da03..1dc9a5e351 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -185,8 +185,8 @@ For shell scripts specifically (not exhaustive): - Even though "local" is not part of POSIX, we make heavy use of it in our test suite. We do not use it in scripted Porcelains, and - hopefully nobody starts using "local" before they are reimplemented - in C ;-) + hopefully nobody starts using "local" before all shells that matter + support it (notably, ksh from AT&T Research does not support it yet). - Some versions of shell do not understand "export variable=value", so we write "variable=value" and then "export variable" on two @@ -204,6 +204,33 @@ For shell scripts specifically (not exhaustive): local variable="$value" local variable="$(command args)" + - The common construct + + VAR=VAL command args + + to temporarily set and export environment variable VAR only while + "command args" is running is handy, but this triggers an + unspecified behaviour according to POSIX when used for a command + that is not an external command (like shell functions). Indeed, + dash 0.5.10.2-6 on Ubuntu 20.04, /bin/sh on FreeBSD 13, and AT&T + ksh all make a temporary assignment without exporting the variable, + in such a case. As it does not work portably across shells, do not + use this syntax for shell functions. A common workaround is to do + an explicit export in a subshell, like so: + + (incorrect) + VAR=VAL func args + + (correct) + ( + VAR=VAL && + export VAR && + func args + ) + + but be careful that the effect "func" makes to the variables in the + current shell will be lost across the subshell boundary. + - Use octal escape sequences (e.g. "\302\242"), not hexadecimal (e.g. "\xc2\xa2") in printf format strings, since hexadecimal escape sequences are not portable. @@ -214,6 +241,16 @@ For C programs: - We use tabs to indent, and interpret tabs as taking up to 8 spaces. + - Nested C preprocessor directives are indented after the hash by one + space per nesting level. + + #if FOO + # include <foo.h> + # if BAR + # include <bar.h> + # endif + #endif + - We try to keep to at most 80 characters per line. - As a Git developer we assume you have a reasonably modern compiler @@ -221,6 +258,14 @@ For C programs: ensure your patch is clear of all compiler warnings we care about, by e.g. "echo DEVELOPER=1 >>config.mak". + - When using DEVELOPER=1 mode, you may see warnings from the compiler + like "error: unused parameter 'foo' [-Werror=unused-parameter]", + which indicates that a function ignores its argument. If the unused + parameter can't be removed (e.g., because the function is used as a + callback and has to match a certain interface), you can annotate + the individual parameters with the UNUSED (or MAYBE_UNUSED) + keyword, like "int foo UNUSED". + - We try to support a wide range of C compilers to compile Git with, including old ones. As of Git v2.35.0 Git requires C99 (we check "__STDC_VERSION__"). You should not use features from a newer C @@ -234,7 +279,7 @@ For C programs: . since around 2007 with 2b6854c863a, we have been using initializer elements which are not computable at load time. E.g.: - const char *args[] = {"constant", variable, NULL}; + const char *args[] = { "constant", variable, NULL }; . since early 2012 with e1327023ea, we have been using an enum definition whose last element is followed by a comma. This, like @@ -266,7 +311,9 @@ For C programs: v12.01, 2022-03-28). - Variables have to be declared at the beginning of the block, before - the first statement (i.e. -Wdeclaration-after-statement). + the first statement (i.e. -Wdeclaration-after-statement). It is + encouraged to have a blank line between the end of the declarations + and the first statement in the block. - NULL pointers shall be written as NULL, not as 0. @@ -286,6 +333,13 @@ For C programs: while( condition ) func (bar+1); + - A binary operator (other than ",") and ternary conditional "?:" + have a space on each side of the operator to separate it from its + operands. E.g. "A + 1", not "A+1". + + - A unary operator (other than "." and "->") have no space between it + and its operand. E.g. "(char *)ptr", not "(char *) ptr". + - Do not explicitly compare an integral value with constant 0 or '\0', or a pointer value with constant NULL. For instance, to validate that counted array <ptr, cnt> is initialized but has no elements, write: @@ -531,6 +585,56 @@ For C programs: use your own debugger and arguments. Example: `GIT_DEBUGGER="ddd --gdb" ./bin-wrappers/git log` (See `wrap-for-bin.sh`.) + - The primary data structure that a subsystem 'S' deals with is called + `struct S`. Functions that operate on `struct S` are named + `S_<verb>()` and should generally receive a pointer to `struct S` as + first parameter. E.g. + + struct strbuf; + + void strbuf_add(struct strbuf *buf, ...); + + void strbuf_reset(struct strbuf *buf); + + is preferred over: + + struct strbuf; + + void add_string(struct strbuf *buf, ...); + + void reset_strbuf(struct strbuf *buf); + + - There are several common idiomatic names for functions performing + specific tasks on a structure `S`: + + - `S_init()` initializes a structure without allocating the + structure itself. + + - `S_release()` releases a structure's contents without freeing the + structure. + + - `S_clear()` is equivalent to `S_release()` followed by `S_init()` + such that the structure is directly usable after clearing it. When + `S_clear()` is provided, `S_init()` shall not allocate resources + that need to be released again. + + - `S_free()` releases a structure's contents and frees the + structure. + + - Function names should be clear and descriptive, accurately reflecting + their purpose or behavior. Arbitrary suffixes that do not add meaningful + context can lead to confusion, particularly for newcomers to the codebase. + + Historically, the '_1' suffix has been used in situations where: + + - A function handles one element among a group that requires similar + processing. + - A recursive function has been separated from its setup phase. + + The '_1' suffix can be used as a concise way to indicate these specific + cases. However, it is recommended to find a more descriptive name wherever + possible to improve the readability and maintainability of the code. + For Perl programs: - Most of the C guidelines above apply. @@ -599,16 +703,30 @@ Program Output Error Messages - - Do not end error messages with a full stop. + - Do not end a single-sentence error message with a full stop. - Do not capitalize the first word, only because it is the first word - in the message ("unable to open %s", not "Unable to open %s"). But + in the message ("unable to open '%s'", not "Unable to open '%s'"). But "SHA-3 not supported" is fine, because the reason the first word is capitalized is not because it is at the beginning of the sentence, but because the word would be spelled in capital letters even when it appeared in the middle of the sentence. - - Say what the error is first ("cannot open %s", not "%s: cannot open") + - Say what the error is first ("cannot open '%s'", not "%s: cannot open"). + + - Enclose the subject of an error inside a pair of single quotes, + e.g. `die(_("unable to open '%s'"), path)`. + + - Unless there is a compelling reason not to, error messages from + porcelain commands should be marked for translation, e.g. + `die(_("bad revision %s"), revision)`. + + - Error messages from the plumbing commands are sometimes meant for + machine consumption and should not be marked for translation, + e.g., `die("bad revision %s", revision)`. + + - BUG("message") are for communicating the specific error to developers, + thus should not be translated. Externally Visible Names @@ -738,78 +856,80 @@ Markup: _<new-branch-name>_ _<template-directory>_ - A placeholder is not enclosed in backticks, as it is not a literal. - When needed, use a distinctive identifier for placeholders, usually made of a qualification and a type: _<git-dir>_ _<key-id>_ - When literal and placeholders are mixed, each markup is applied for - each sub-entity. If they are stuck, a special markup, called - unconstrained formatting is required. - Unconstrained formating for placeholders is __<like-this>__ - Unconstrained formatting for literal formatting is ++like this++ - `--jobs` _<n>_ - ++--sort=++__<key>__ - __<directory>__++/.git++ - ++remote.++__<name>__++.mirror++ + Git's Asciidoc processor has been tailored to treat backticked text + as complex synopsis. When literal and placeholders are mixed, you can + use the backtick notation which will take care of correctly typesetting + the content. + `--jobs <n>` + `--sort=<key>` + `<directory>/.git` + `remote.<name>.mirror` + `ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>` - caveat: ++ unconstrained format is not verbatim and may expand - content. Use Asciidoc escapes inside them. +As a side effect, backquoted placeholders are correctly typeset, but +this style is not recommended. Synopsis Syntax - Syntax grammar is formatted neither as literal nor as placeholder. + The synopsis (a paragraph with [synopsis] attribute) is automatically + formatted by the toolchain and does not need typesetting. A few commented examples follow to provide reference when writing or modifying command usage strings and synopsis sections in the manual pages: Possibility of multiple occurrences is indicated by three dots: - _<file>_... + <file>... (One or more of <file>.) Optional parts are enclosed in square brackets: - [_<file>_...] + [<file>...] (Zero or more of <file>.) - ++--exec-path++[++=++__<path>__] + An optional parameter needs to be typeset with unconstrained pairs + [<repository>] + + --exec-path[=<path>] (Option with an optional argument. Note that the "=" is inside the brackets.) - [_<patch>_...] + [<patch>...] (Zero or more of <patch>. Note that the dots are inside, not outside the brackets.) Multiple alternatives are indicated with vertical bars: - [`-q` | `--quiet`] - [`--utf8` | `--no-utf8`] + [-q | --quiet] + [--utf8 | --no-utf8] Use spacing around "|" token(s), but not immediately after opening or before closing a [] or () pair: - Do: [`-q` | `--quiet`] - Don't: [`-q`|`--quiet`] + Do: [-q | --quiet] + Don't: [-q|--quiet] Don't use spacing around "|" tokens when they're used to separate the alternate arguments of an option: - Do: ++--track++[++=++(`direct`|`inherit`)]` - Don't: ++--track++[++=++(`direct` | `inherit`)] + Do: --track[=(direct|inherit)] + Don't: --track[=(direct | inherit)] Parentheses are used for grouping: - [(_<rev>_ | _<range>_)...] + [(<rev>|<range>)...] (Any number of either <rev> or <range>. Parens are needed to make it clear that "..." pertains to both <rev> and <range>.) - [(`-p` _<parent>_)...] + [(-p <parent>)...] (Any number of option -p, each with one <parent> argument.) - `git remote set-head` _<name>_ (`-a` | `-d` | _<branch>_) + git remote set-head <name> (-a|-d|<branch>) (One and only one of "-a", "-d" or "<branch>" _must_ (no square brackets) be provided.) And a somewhat more contrived example: - `--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]` + --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]] Here "=" is outside the brackets, because "--diff-filter=" is a valid usage. "*" has its own pair of brackets, because it can (optionally) be specified only when one or more of the letters is diff --git a/Documentation/DecisionMaking.txt b/Documentation/DecisionMaking.txt index dbb4c1f569..b43c472ae5 100644 --- a/Documentation/DecisionMaking.txt +++ b/Documentation/DecisionMaking.txt @@ -54,7 +54,7 @@ implementation, for very large changes). For non-technical decisions such as community norms or processes, it is up to the community as a whole to implement and sustain agreed-upon changes. -The project leadership committe (PLC) may help the implementation of +The project leadership committee (PLC) may help the implementation of policy decisions. diff --git a/Documentation/Makefile b/Documentation/Makefile index 1bd23fbeef..0f55baa252 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -118,6 +118,7 @@ TECH_DOCS += technical/multi-pack-index TECH_DOCS += technical/pack-heuristics TECH_DOCS += technical/parallel-checkout TECH_DOCS += technical/partial-clone +TECH_DOCS += technical/platform-support TECH_DOCS += technical/racy-git TECH_DOCS += technical/reftable TECH_DOCS += technical/scalar diff --git a/Documentation/RelNotes/2.45.0.txt b/Documentation/RelNotes/2.45.0.txt index fec193679f..aa0315259b 100644 --- a/Documentation/RelNotes/2.45.0.txt +++ b/Documentation/RelNotes/2.45.0.txt @@ -9,7 +9,7 @@ UI, Workflows & Features With "git init --ref-format=reftable", hopefully it would be a lot more efficient to manage a repository with many references. - * "git checkout -p" and friends learned that that "@" is a synonym + * "git checkout -p" and friends learned that "@" is a synonym for "HEAD". * Variants of vimdiff learned to honor mergetool.<variant>.layout diff --git a/Documentation/RelNotes/2.46.0.txt b/Documentation/RelNotes/2.46.0.txt index b25475918a..c06a04a91b 100644 --- a/Documentation/RelNotes/2.46.0.txt +++ b/Documentation/RelNotes/2.46.0.txt @@ -78,7 +78,7 @@ UI, Workflows & Features turn on cover letters automatically (unless told never to enable cover letter with "--no-cover-letter" and such). - * The "--heads" option of "ls-remote" and "show-ref" has been been + * The "--heads" option of "ls-remote" and "show-ref" has been deprecated; "--branches" replaces "--heads". * For over a year, setting add.interactive.useBuiltin configuration diff --git a/Documentation/RelNotes/2.46.1.txt b/Documentation/RelNotes/2.46.1.txt new file mode 100644 index 0000000000..e55c2c4a46 --- /dev/null +++ b/Documentation/RelNotes/2.46.1.txt @@ -0,0 +1,75 @@ +Git 2.46.1 Release Notes +======================== + +This release is primarily to merge fixes accumulated on the 'master' +front to prepare for 2.47 release that are still relevant to 2.46.x +maintenance track. + +Fixes since Git 2.46 +-------------------- + + * "git checkout --ours" (no other arguments) complained that the + option is incompatible with branch switching, which is technically + correct, but found confusing by some users. It now says that the + user needs to give pathspec to specify what paths to checkout. + + * It has been documented that we avoid "VAR=VAL shell_func" and why. + + * "git add -p" by users with diff.suppressBlankEmpty set to true + failed to parse the patch that represents an unmodified empty line + with an empty line (not a line with a single space on it), which + has been corrected. + + * "git rebase --help" referred to "offset" (the difference between + the location a change was taken from and the change gets replaced) + incorrectly and called it "fuzz", which has been corrected. + + * "git notes add -m '' --allow-empty" and friends that take prepared + data to create notes should not invoke an editor, but it started + doing so since Git 2.42, which has been corrected. + + * An expensive operation to prepare tracing was done in re-encoding + code path even when the tracing was not requested, which has been + corrected. + + * Perforce tests have been updated. + + * The credential helper to talk to OSX keychain sometimes sent + garbage bytes after the username, which has been corrected. + + * A recent update broke "git ls-remote" used outside a repository, + which has been corrected. + + * "git config --value=foo --fixed-value section.key newvalue" barfed + when the existing value in the configuration file used the + valueless true syntax, which has been corrected. + + * "git reflog expire" failed to honor annotated tags when computing + reachable commits. + + * A flakey test and incorrect calls to strtoX() functions have been + fixed. + + * Follow-up on 2.45.1 regression fix. + + * "git rev-list ... | git diff-tree -p --remerge-diff --stdin" should + behave more or less like "git log -p --remerge-diff" but instead it + crashed, forgetting to prepare a temporary object store needed. + + * The patch parser in "git patch-id" has been tightened to avoid + getting confused by lines that look like a patch header in the log + message. + + * "git bundle unbundle" outside a repository triggered a BUG() + unnecessarily, which has been corrected. + + * The code forgot to discard unnecessary in-core commit buffer data + for commits that "git log --skip=<number>" traversed but omitted + from the output, which has been corrected. + + * "git verify-pack" and "git index-pack" started dying outside a + repository, which has been corrected. + + * A corner case bug in "git stash" was fixed. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.46.2.txt b/Documentation/RelNotes/2.46.2.txt new file mode 100644 index 0000000000..613386878d --- /dev/null +++ b/Documentation/RelNotes/2.46.2.txt @@ -0,0 +1,23 @@ +Git 2.46.2 Release Notes +======================== + +This release is primarily to merge changes to unbreak the 32-bit +GitHub actions jobs we use for CI testing, so that we can release +real fixes for the 2.46.x track after they pass CI. + +It also reverts the "git patch-id" change that went into 2.46.1, +as it seems to have got a regression reported (I haven't verified, +but it is better to keep a known breakage than adding an unintended +regression). + +Other than that, a handful of minor bugfixes are included. + + * In a few corner cases "git diff --exit-code" failed to report + "changes" (e.g., renamed without any content change), which has + been corrected. + + * Cygwin does have /dev/tty support that is needed by things like + single-key input mode. + + * The interpret-trailers command failed to recognise the end of the + message when the commit log ends in an incomplete line. diff --git a/Documentation/RelNotes/2.47.0.txt b/Documentation/RelNotes/2.47.0.txt new file mode 100644 index 0000000000..b63c3364af --- /dev/null +++ b/Documentation/RelNotes/2.47.0.txt @@ -0,0 +1,342 @@ +Git v2.47 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * Many Porcelain commands that internally use the merge machinery + were taught to consistently honor the diff.algorithm configuration. + + * A few descriptions in "git show-ref -h" have been clarified. + + * A 'P' command to "git add -p" that passes the patch hunk to the + pager has been added. + + * "git grep -W" omits blank lines that follow the found function at + the end of the file, just like it omits blank lines before the next + function. + + * The value of http.proxy can have "path" at the end for a socks + proxy that listens to a unix-domain socket, but we started to + discard it when we taught proxy auth code path to use the + credential helpers, which has been corrected. + + * The code paths to compact multiple reftable files have been updated + to correctly deal with multiple compaction triggering at the same + time. + + * Support to specify ref backend for submodules has been enhanced. + + * "git svn" has been taught about svn:global-ignores property + recent versions of Subversion has. + + * The default object hash and ref backend format used to be settable + only with explicit command line option to "git init" and + environment variables, but now they can be configured in the user's + global and system wide configuration. + + * "git send-email" learned "--translate-aliases" option that reads + addresses from the standard input and emits the result of applying + aliases on them to the standard output. + + * 'git for-each-ref' learned a new "--format" atom to find the branch + that the history leading to a given commit "%(is-base:<commit>)" is + likely based on. + + * The command line prompt support used to be littered with bash-isms, + which has been corrected to work with more shells. + + * Support for the RUNTIME_PREFIX feature has been added to z/OS port. + + * "git send-email" learned "--mailmap" option to allow rewriting the + recipient addresses. + + * "git mergetool" learned to use VSCode as a merge backend. + + * "git pack-redundant" has been marked for removal in Git 3.0. + + * One-line messages to "die" and other helper functions will get LF + added by these helper functions, but many existing messages had an + unnecessary LF at the end, which have been corrected. + + * The "scalar clone" command learned the "--no-tags" option. + + * The environment GIT_ADVICE has been intentionally kept undocumented + to discourage its use by interactive users. Add documentation to + help tool writers. + + * "git apply --3way" learned to take "--ours" and other options. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * A build tweak knob has been simplified by not setting the value + that is already the default; another unused one has been removed. + + * A CI job that use clang-format to check coding style issues in new + code has been added. + + * The reviewing guidelines document now explicitly encourages people + to give positive reviews and how. + + * Test script linter has been updated to catch an attempt to use + one-shot export construct "VAR=VAL func" for shell functions (which + does not work for some shells) better. + + * Some project conventions have been added to CodingGuidelines. + + * In the refs subsystem, implicit reliance of the_repository has been + eliminated; the repository associated with the ref store object is + used instead. + + * Various tests in reftable library have been rewritten using the unit test + framework. + + * A test that fails on an unusually slow machine was found, and made + less likely to cause trouble by lengthening the expiry value it + uses. + + * An existing test of hashmap API has been rewritten with the + unit-test framework. + + * A policy document that describes platform support levels and + expectation on platform stakeholders has been introduced. + + * The refs API has been taught to give symref target information to + the users of ref iterators, allowing for-each-ref and friends to + avoid an extra ref_resolve_* API call per a symbolic ref. + + * Unit-test framework has learned a simple control structure to allow + embedding test statements in-line instead of having to create a new + function to contain them. + + * Incremental updates of multi-pack index files is getting worked on. + + * Use of API functions that implicitly depend on the_repository + object in the config subsystem has been rewritten to pass a + repository object through the callchain. + + * Unused parameters have been either marked as UNUSED to squelch + -Wunused warnings or dropped from many functions.. + + * The code in the reftable library has been cleaned up by discarding + unused "generic" interface. + + * The underlying machinery for "git diff-index" has long been made to + expand the sparse index as needed, but the command fully expanded + the sparse index upfront, which now has been taught not to do. + + * More trace2 events at key points on push and fetch code paths have + been added. + + * Make our codebase compilable with the -Werror=unused-parameter + option. + + * "git cat-file" works well with the sparse-index, and gets marked as + such. + + * CI started failing completely for linux32 jobs, as the step to + upload failed test directory uses GitHub actions that is deprecated + and is now disabled. + + * Import clar unit tests framework libgit2 folks invented for our + use. + + * The error messages from the test script checker have been improved. + + * The convention to calling into built-in command implementation has + been updated to pass the repository, if known, together with the + prefix value. + + * "git apply" had custom buffer management code that predated before + use of strbuf got widespread, which has been updated to use strbuf, + which also plugged some memory leaks. + + * The reftable backend learned to more efficiently handle exclude + patterns while enumerating the refs. + + * CI updates. FreeBSD image has been updated to 13.4. + (merge 2eeb29702e cb/ci-freebsd-13-4 later to maint). + + * Give timeout to the locking code to write to reftable, instead of + failing on the first failure without retrying. + + * The checksum at the tail of files are now computed without + collision detection protection. This is safe as the consumer of + the information to protect itself from replay attacks checks for + hash collisions independently. + + +Fixes since v2.46 +----------------- + + * "git add -p" by users with diff.suppressBlankEmpty set to true + failed to parse the patch that represents an unmodified empty line + with an empty line (not a line with a single space on it), which + has been corrected. + + * "git checkout --ours" (no other arguments) complained that the + option is incompatible with branch switching, which is technically + correct, but found confusing by some users. It now says that the + user needs to give pathspec to specify what paths to checkout. + + * It has been documented that we avoid "VAR=VAL shell_func" and why. + + * "git rebase --help" referred to "offset" (the difference between + the location a change was taken from and the change gets replaced) + incorrectly and called it "fuzz", which has been corrected. + + * "git notes add -m '' --allow-empty" and friends that take prepared + data to create notes should not invoke an editor, but it started + doing so since Git 2.42, which has been corrected. + + * An expensive operation to prepare tracing was done in re-encoding + code path even when the tracing was not requested, which has been + corrected. + + * More leakfixes. + + * The credential helper to talk to OSX keychain sometimes sent + garbage bytes after the username, which has been corrected. + + * A recent update broke "git ls-remote" used outside a repository, + which has been corrected. + + * The patch parser in 'git apply' has been a bit more lenient against + unexpected mode bits, like 100664, recorded on extended header lines. + + * "git config --value=foo --fixed-value section.key newvalue" barfed + when the existing value in the configuration file used the + valueless true syntax, which has been corrected. + + * The patch parser in "git patch-id" has been tightened to avoid + getting confused by lines that look like a patch header in the log + message. + + * "git reflog expire" failed to honor annotated tags when computing + reachable commits. + + * A flakey test and incorrect calls to strtoX() functions have been + fixed. + + * Follow-up on 2.45.1 regression fix. + + * "git rev-list ... | git diff-tree -p --remerge-diff --stdin" should + behave more or less like "git log -p --remerge-diff" but instead it + crashed, forgetting to prepare a temporary object store needed. + + * "git bundle unbundle" outside a repository triggered a BUG() + unnecessarily, which has been corrected. + + * Maintenance tasks other than "gc" now properly go background when + "git maintenance" runs them. + + * We created a useless pseudo-merge reachability bitmap that is about + 0 commits, and attempted to include commits that are not in packs, + which made no sense. These bugs have been corrected. + (merge a72dfab8b8 tb/pseudo-merge-bitmap-fixes later to maint). + + * "git rebase -x --quiet" was not quiet, which was corrected. + + * The code path for compacting reftable files saw some bugfixes + against concurrent operation. + + * The code forgot to discard unnecessary in-core commit buffer data + for commits that "git log --skip=<number>" traversed but omitted + from the output, which has been corrected. + + * "git verify-pack" and "git index-pack" started dying outside a + repository, which has been corrected. + + * A data corruption bug when multi-pack-index is used and the same + objects are stored in multiple packfiles has been corrected. + + * "git pack-refs --auto" for the files backend was too aggressive, + which has been a bit tamed. + (merge c3459ae9ef ps/pack-refs-auto-heuristics later to maint). + + * A file descriptor left open is now properly closed when "git + sparse-checkout" updates the sparse patterns. + + * In a few corner cases "git diff --exit-code" failed to report + "changes" (e.g., renamed without any content change), which has + been corrected. + + * Cygwin does have /dev/tty support that is needed by things like + single-key input mode. + + * The interpret-trailers command failed to recognise the end of the + message when the commit log ends in an incomplete line. + + * "git rebase --autostash" failed to resurrect the autostashed + changes when the command gets aborted after giving back control + asking for hlep in conflict resolution. + (merge bf6ab087d1 pw/rebase-autostash-fix later to maint). + + * The "imap-send" now allows to be compiled with NO_OPENSSL and + OPENSSL_SHA1 defined together. + (merge 997950a750 jk/no-openssl-with-openssl-sha1 later to maint). + + * The support to customize build options to adjust for older versions + and/or older systems for the interop tests has been improved. + (merge 22ef5f02a8 jk/interop-test-build-options later to maint). + + * Update the character width table for Unicode 16. + (merge 44dc651132 bb/unicode-width-table-16 later to maint). + + * In Git 2.39, Git.pm stopped working in a bare repository, which has + been corrected. + (merge d3edb0bdde jk/git-pm-bare-repo-fix later to maint). + + * When a remote-helper dies before Git writes to it, SIGPIPE killed + Git silently. We now explain the situation a bit better to the end + user in our error message. + (merge 6e7fac9bca jk/diag-unexpected-remote-helper-death later to maint). + + * A few usability fixes to "git jump" (in contrib/). + (merge 083b82544d jk/jump-quickfix-fixes later to maint). + + * "git diff --exit-code" ignored modified binary files, which has + been corrected. + (merge 9a41735af6 rs/diff-exit-code-binary later to maint). + + * When a subprocess to work in a submodule spawned by "git submodule" + fails with SIGPIPE, the parent Git process caught the death of it, + but gave a generic "failed to work in that submodule", which was + misleading. We now behave as if the parent got SIGPIPE and die. + (merge 082caf527e pw/submodule-process-sigpipe later to maint). + + * "git archive" with pathspec magic that uses the attribute + information did not work well, which has been corrected. + (merge 296743a7ca rs/archive-with-attr-pathspec-fix later to maint). + + * Background tasks "git maintenance" runs may need to use credential + information when going over the network, but a credential helper + may work only in an interactive environment, and end up blocking a + scheduled task waiting for UI. Credential helpers can now behave + differently when they are not running interactively. + (merge b9183b0a02 ds/background-maintenance-with-credential later to maint). + + * "git --git-dir=nowhere cmd" failed to properly notice that it + wasn't in any repository while processing includeIf.onbranch + configuration and instead crashed. + + * When "git sparse-checkout disable" turns a sparse checkout into a + regular checkout, the index is fully expanded. This totally + expected behaviour however had an "oops, we are expanding the + index" advice message, which has been corrected. + (merge 537e516a39 ds/sparse-checkout-expansion-advice later to maint). + + * macOS with fsmonitor daemon can hang forever when a submodule is + involved, which has been corrected. + + * Other code cleanup, docfix, build fix, etc. + (merge be10ac7037 jc/mailinfo-header-cleanup later to maint). + (merge 4460e052e0 jc/range-diff-lazy-setup later to maint). + (merge 0627c58e7a ak/typofixes later to maint). + (merge 83799f1500 jk/t9001-deflake later to maint). + (merge e02cc08a88 ak/typofix-2.46-maint later to maint). + (merge 5c5d29e1c4 ps/ci-gitlab-upgrade later to maint). + (merge 9c4c840901 jc/doc-discarding-stalled-topics later to maint). + (merge 5e6f359f6b ds/read-cache-mempool-leakfix later to maint). diff --git a/Documentation/RelNotes/2.47.1.txt b/Documentation/RelNotes/2.47.1.txt new file mode 100644 index 0000000000..39206c09fd --- /dev/null +++ b/Documentation/RelNotes/2.47.1.txt @@ -0,0 +1,31 @@ +Git 2.47.1 Release Notes +======================== + +This is to flush accumulated fixes since 2.47.0 on the 'master' +front down to the maintenance track. + + +Fixes since Git 2.47 +-------------------- + + * Use after free and double freeing at the end in "git log -L... -p" + had been identified and fixed. + + * On macOS, fsmonitor can fall into a race condition that results in + a client waiting forever to be notified for an event that have + already happened. This problem has been corrected. + + * "git maintenance start" crashed due to an uninitialized variable + reference, which has been corrected. + + * Fail gracefully instead of crashing when attempting to write the + contents of a corrupt in-core index as a tree object. + + * A "git fetch" from the superproject going down to a submodule used + a wrong remote when the default remote names are set differently + between them. + + * The "gitk" project tree has been synchronized again with its new + maintainer, Johannes Sixt. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt new file mode 100644 index 0000000000..802e9a96e5 --- /dev/null +++ b/Documentation/RelNotes/2.48.0.txt @@ -0,0 +1,253 @@ +Git v2.48 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * A new configuration variable remote.<name>.serverOption makes the + transport layer act as if the --serverOption=<value> option is + given from the command line. + + * "git rebase --rebase-merges" now uses branch names as labels when + able. + + * Describe the policy to introduce breaking changes. + + * Teach 'git notes add' and 'git notes append' a new '-e' flag, + instructing them to open the note in $GIT_EDITOR before saving. + + * Documentation for "git bundle" saw improvements to more prominently + call out the use of '--all' when creating bundles. + + * Drop support for older libcURL and Perl. + + * End-user experience of "git mergetool" when the command errors out + has been improved. + + * "git bundle --unbundle" and "git clone" running on a bundle file + both learned to trigger fsck over the new objects with configurable + fck check levels. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * Document "amlog" notes. + + * The way AsciiDoc is used for SYNOPSIS part of the manual pages has + been revamped. The sources, at least for the simple cases, got + vastly pleasant to work with. + + * The reftable library is now prepared to expect that the memory + allocation function given to it may fail to allocate and to deal + with such an error. + + * An extra worktree attached to a repository points at each other to + allow finding the repository from the worktree and vice versa + possible. Turn this linkage to relative paths. + + * Enable Windows-based CI in GitLab. + + * Commands that can also work outside Git have learned to take the + repository instance "repo" when we know we are in a repository, and + NULL when we are not, in a parameter. The uses of the_repository + variable in a few of them have been removed using the new calling + convention. + + * The reftable sub-system grew a new reftable-specific strbuf + replacement to reduce its dependency on Git-specific data + structures. + + * The ref-filter machinery learns to recognize and avoid cases where + sorting would be redundant. + + * Various platform compatibility fixes split out of the larger effort + to use Meson as the primary build tool. + + * Treat ECONNABORTED the same as ECONNRESET in 'git credential-cache' + to work around a possible Cygwin regression. This resolves a race + condition caused by changes in Cygwin's handling of socket + closures, allowing the client to exit cleanly when encountering + ECONNABORTED. + + * Demonstrate an assertion failure in 'git mv'. + + * Documentation update to clarify that 'uploadpack.allowAnySHA1InWant' + implies both 'allowTipSHA1InWant' and 'allowReachableSHA1InWant'. + + * Replace various calls to atoi() with strtol_i() and strtoul_ui(), + and add improved error handling. + + * Documentation updates to 'git-update-ref(1)'. + + * Update the project's CodingGuidelines to discourage naming functions + with a "_1()" suffix. + + * Updates the '.clang-format' to match project conventions. + + * Centralize documentation for repository extensions into a single place. + + * Buildfix and upgrade of Clar to a newer version. + + * Documentation mark-up updates. + + * Renaming a handful of variables and structure fields. + + * Fix for clar unit tests to support CMake build. + + * C23 compatibility updates. + + * GCC 15 compatibility updates. + + * We now ensure "index-pack" is used with the "--promisor" option + only during a "git fetch". + + * The migration procedure between two ref backends has been optimized. + + * "git fsck" learned to issue warnings on "curiously formatted" ref + contents that have always been taken valid but something Git + wouldn't have written itself (e.g., missing terminating end-of-line + after the full object name). + + * Work around Coverity warning that would not trigger in practice. + + * Built-in Git subcommands are supplied the repository object to work + with; they learned to do the same when they invoke sub-subcommands. + + * Drop support for ancient environments in various CI jobs. + + * Isolates the reftable subsystem from the rest of Git's codebase by + using fewer pieces of Git's infrastructure. + + * Optimize reading random references out of the reftable backend by + allowing reuse of iterator objects. + + * Backport oss-fuzz tests for us to our codebase. + + * Introduce a new repository extension to prevent older Git versions + from mis-interpreting worktrees created with relative paths. + + * Yet another "pass the repository through the callchain" topic. + + +Fixes since v2.47 +----------------- + + * Doc update to clarify how periodical maintenance are scheduled, + spread across time to avoid thundering hurds. + + * Use after free and double freeing at the end in "git log -L... -p" + had been identified and fixed. + + * On macOS, fsmonitor can fall into a race condition that results in + a client waiting forever to be notified for an event that have + already happened. This problem has been corrected. + + * "git maintenance start" crashed due to an uninitialized variable + reference, which has been corrected. + + * Fail gracefully instead of crashing when attempting to write the + contents of a corrupt in-core index as a tree object. + + * A "git fetch" from the superproject going down to a submodule used + a wrong remote when the default remote names are set differently + between them. + + * Fixes compile time warnings with 64-bit MSVC. + + * Teaches 'shortlog' to explicitly use SHA-1 when operating outside + of a repository. + + * Fix 'git grep' regression on macOS by disabling lookahead when + encountering invalid UTF-8 byte sequences. + + * The dumb-http code regressed when the result of re-indexing a pack + yielded an *.idx file that differs in content from the *.idx file + it downloaded from the remote. This has been corrected by no longer + relying on: the *.idx file we got from the remote. + + * When called with '--left-right' and '--use-bitmap-index', 'rev-list' + will produce output without any left/right markers, which has been + corrected. + + * More leakfixes. + + * Test modernization. + + * The "--shallow-exclude=<ref>" option to various history transfer + commands takes a ref, not an arbitrary revision. + + * A regression where commit objects missing from a commit-graph can + cause an infinite loop when doing a fetch in a partial clone has + been fixed. + + * The MinGW compatibility layer has been taught to support POSIX + semantics for atomic renames when other process(es) have a file + opened at the destination path. + + * "git gc" discards any objects that are outside promisor packs that + are referred to by an object in a promisor pack, and we do not + refetch them from the promisor at runtime, resulting an unusable + repository. Work it around by including these objects in the + referring promisor pack at the receiving end of the fetch. + + * Avoid build/test breakage on a system without working malloc debug + support dynamic library. + (merge 72ad6dc368 jk/test-malloc-debug-check later to maint). + + * Double-free fix. + (merge fe17a25905 jk/fetch-prefetch-double-free-fix later to maint). + + * Use of some uninitialized variables in "git difftool" has been + corrected. + + * Object reuse code based on multi-pack-index sent an unwanted copy + of object. + (merge e199290592 tb/multi-pack-reuse-dupfix later to maint). + + * "git fast-import" can be tricked into a replace ref that maps an + object to itself, which is a useless thing to do. + (merge 5e904f1a4a en/fast-import-avoid-self-replace later to maint). + + * The ref-transaction hook triggered for reflog updates, which has + been corrected. + (merge b886db48c6 kn/ref-transaction-hook-with-reflog later to maint). + + * Give a bit of advice/hint message when "git maintenance" stops finding a + lock file left by another instance that still is potentially running. + (merge ba874d1dac ps/gc-stale-lock-warning later to maint). + + * Use the right helper program to measure file size in performance tests. + (merge 3f97f1bce6 tb/use-test-file-size-more later to maint). + + * A double-free that may not trigger in practice by luck has been + corrected in the reference resolution code. + (merge b6318cf23a sj/refs-symref-referent-fix later to maint). + + * The sequencer failed to honor core.commentString in some places. + + * Describe a case where an option value needs to be spelled as a + separate argument, i.e. "--opt val", not "--opt=val". + (merge 1bc1e94091 jc/doc-opt-tilde-expand later to maint). + + * Loosen overly strict ownership check introduced in the recent past, + to keep the promise "cloning a suspicious repository is a safe + first step to inspect it". + (merge 0ffb5a6bf1 bc/allow-upload-pack-from-other-people later to maint). + + * "git fast-import" learned to reject paths with ".." and "." as + their components to avoid creating invalid tree objects. + (merge 8cb4c6e62f en/fast-import-verify-path later to maint). + + * The --ancestry-path option is designed to be given a commit that is + on the path, which was not documented, which has been corrected. + (merge bc1a980759 kk/doc-ancestry-path later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge 77af53f56f aa/t7300-modernize later to maint). + (merge dcd590a39d bf/t-readme-mention-reftable later to maint). + (merge 68e3c69efa kh/trailer-in-glossary later to maint). + (merge 91f88f76e6 tb/boundary-traversal-fix later to maint). + (merge 168ebb7159 jc/doc-error-message-guidelines later to maint). + (merge 18693d7d65 kh/doc-bundle-typofix later to maint). + (merge e2f5d3b491 kh/doc-update-ref-grammofix later to maint). diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt index 515d470d23..6534643cff 100644 --- a/Documentation/ReviewingGuidelines.txt +++ b/Documentation/ReviewingGuidelines.txt @@ -72,12 +72,29 @@ guidance, and concrete tips for interacting with patches on the mailing list. could fix it. This not only helps the author to understand and fix the issue, it also deepens and improves your understanding of the topic. -- Reviews do not need to exclusively point out problems. Feel free to "think out +- Reviews do not need to exclusively point out problems. Positive + reviews indicate that it is not only the original author of the + patches who care about the issue the patches address, and are + highly encouraged. + +- Do not hesitate to give positive reviews on a series from your + work colleague. If your positive review is written well, it will + not make you look as if you two are representing corporate + interest on a series that is otherwise uninteresting to other + community members and shoving it down their throat. + +- Write a positive review in such a way that others can understand + why you support the goal, the approach, and the implementation the + patches took. Make sure to demonstrate that you did thoroughly read + the series and understood problem area well enough to be able to + say that the patches are written well. Feel free to "think out loud" in your review: describe how you read & understood a complex section of a patch, ask a question about something that confused you, point out something - you found exceptionally well-written, etc. In particular, uplifting feedback - goes a long way towards encouraging contributors to participate more actively - in the Git community. + you found exceptionally well-written, etc. + +- In particular, uplifting feedback goes a long way towards + encouraging contributors to participate more actively in the Git + community. ==== Performing your review - Provide your review comments per-patch in a plaintext "Reply-All" email to the diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index d8a8caa791..db17bc7fe2 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -412,13 +412,13 @@ Also notice that a real name is used in the `Signed-off-by` trailer. Please don't hide your real name. [[commit-trailers]] -If you like, you can put extra tags at the end: +If you like, you can put extra trailers at the end: . `Reported-by:` is used to credit someone who found the bug that the patch attempts to fix. . `Acked-by:` says that the person who is more familiar with the area the patch attempts to modify liked the patch. -. `Reviewed-by:`, unlike the other tags, can only be offered by the +. `Reviewed-by:`, unlike the other trailers, can only be offered by the reviewers themselves when they are completely satisfied with the patch after a detailed analysis. . `Tested-by:` is used to indicate that the person applied the patch @@ -436,7 +436,7 @@ While you can also create your own trailer if the situation warrants it, we encourage you to instead use one of the common trailers in this project highlighted above. -Only capitalize the very first letter of tags, i.e. favor +Only capitalize the very first letter of the trailer, i.e. favor "Signed-off-by" over "Signed-Off-By" and "Acked-by:" over "Acked-By". [[git-tools]] diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 60f76f43ed..f6da6d1fbd 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -28,6 +28,10 @@ ifdef::backend-docbook[] {0#<citerefentry>} {0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>} {0#</citerefentry>} + +[literal-inlinemacro] +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<emphasis>\1</emphasis>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<literal>\2</literal>', re.sub(r'(\.\.\.?)([^\]$.])', r'<literal>\1</literal>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} + endif::backend-docbook[] ifdef::backend-docbook[] @@ -56,4 +60,20 @@ ifdef::backend-xhtml11[] git-relative-html-prefix= [linkgit-inlinemacro] <a href="{git-relative-html-prefix}{target}.html">{target}{0?({0})}</a> + +[literal-inlinemacro] +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<em>\1</em>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<code>\2</code>', re.sub(r'(\.\.\.?)([^\]$.])', r'<code>\1</code>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} + +endif::backend-xhtml11[] + +ifdef::backend-docbook[] +ifdef::doctype-manpage[] +[paradef-default] +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<phrase>\\0</phrase>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1<literal>\\2</literal>!g;s!<[-a-zA-Z0-9.]\\+>!<emphasis>\\0</emphasis>!g'" +endif::doctype-manpage[] +endif::backend-docbook[] + +ifdef::backend-xhtml11[] +[paradef-default] +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<span>\\0</span>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1<code>\\2</code>!g;s!<[-a-zA-Z0-9.]\\+>!<em>\\0</em>!g'" endif::backend-xhtml11[] diff --git a/Documentation/asciidoctor-extensions.rb b/Documentation/asciidoctor-extensions.rb index d906a00803..cb24480b63 100644 --- a/Documentation/asciidoctor-extensions.rb +++ b/Documentation/asciidoctor-extensions.rb @@ -1,5 +1,7 @@ require 'asciidoctor' require 'asciidoctor/extensions' +require 'asciidoctor/converter/docbook5' +require 'asciidoctor/converter/html5' module Git module Documentation @@ -39,10 +41,95 @@ module Git output end end + + class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor + + use_dsl + named :synopsis + parse_content_as :simple + + def process parent, reader, attrs + outlines = reader.lines.map do |l| + l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2') + .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__') + .gsub(']', ']{empty}') + end + create_block parent, :verse, outlines, attrs + end + end + + class GitDBConverter < Asciidoctor::Converter::DocBook5Converter + + extend Asciidoctor::Converter::Config + register_for 'docbook5' + + def convert_inline_quoted node + if (type = node.type) == :asciimath + # NOTE fop requires jeuclid to process mathml markup + asciimath_available? ? %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>) : %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>) + elsif type == :latexmath + # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math + %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>) + elsif type == :monospaced + node.text.gsub(/(\.\.\.?)([^\]$.])/, '<literal>\1</literal>\2') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '<emphasis>\1</emphasis>') + else + open, close, supports_phrase = QUOTE_TAGS[type] + text = node.text + if node.role + if supports_phrase + quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close}) + else + quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close}) + end + else + quoted_text = %(#{open}#{text}#{close}) + end + node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text + end + end + end + + # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis + class GitHTMLConverter < Asciidoctor::Converter::Html5Converter + + extend Asciidoctor::Converter::Config + register_for 'html5' + + def convert_inline_quoted node + if node.type == :monospaced + node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>') + .gsub(/(<[-a-zA-Z0-9.]+>)/, '<em>\1</em>') + + else + open, close, tag = QUOTE_TAGS[node.type] + if node.id + class_attr = node.role ? %( class="#{node.role}") : '' + if tag + %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close}) + else + %(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>) + end + elsif node.role + if tag + %(#{open.chop} class="#{node.role}">#{node.text}#{close}) + else + %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>) + end + else + %(#{open}#{node.text}#{close}) + end + end + end + end end end Asciidoctor::Extensions.register do inline_macro Git::Documentation::LinkGitProcessor, :linkgit + block Git::Documentation::SynopsisBlock postprocessor Git::Documentation::DocumentPostProcessor end diff --git a/Documentation/config/add.txt b/Documentation/config/add.txt index 4d753f006e..7497533cbc 100644 --- a/Documentation/config/add.txt +++ b/Documentation/config/add.txt @@ -1,7 +1,12 @@ -add.ignoreErrors:: -add.ignore-errors (deprecated):: - Tells 'git add' to continue adding files when some files cannot be - added due to indexing errors. Equivalent to the `--ignore-errors` - option of linkgit:git-add[1]. `add.ignore-errors` is deprecated, - as it does not follow the usual naming convention for configuration - variables. +`add.ignoreErrors`:: +`add.ignore-errors` (deprecated):: + Tells `git add` to continue adding files when some files cannot be + added due to indexing errors. +ifdef::git-add[] + Equivalent to the `--ignore-errors` option. +endif::git-add[] +ifndef::git-add[] + Equivalent to the `--ignore-errors` option of linkgit:git-add[1]. +endif::git-add[] + `add.ignore-errors` is deprecated, as it does not follow the usual + naming convention for configuration variables. diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index 0ba8989820..257db58918 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -2,7 +2,13 @@ advice.*:: These variables control various optional help messages designed to aid new users. When left unconfigured, Git will give the message alongside instructions on how to squelch it. You can tell Git - that you do not need the help message by setting these to `false`: + that you have understood the issue and no longer need a specific + help message by setting the corresponding variable to `false`. ++ +As they are intended to help human users, these messages are output to +the standard error. When tools that run Git as a subprocess find them +disruptive, they can set `GIT_ADVICE=0` in the environment to squelch +all advice messages. + -- addEmbeddedRepo:: diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt index 60ca9f2b68..8f6d8e7754 100644 --- a/Documentation/config/core.txt +++ b/Documentation/config/core.txt @@ -366,7 +366,7 @@ default in a bare repository. core.repositoryFormatVersion:: Internal variable identifying the repository format and layout - version. + version. See linkgit:gitrepository-layout[5]. core.sharedRepository:: When 'group' (or 'true'), the repository is made shareable between diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt index 0221c3e620..470482ff4c 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.txt @@ -9,6 +9,14 @@ credential.helper:: Note that multiple helpers may be defined. See linkgit:gitcredentials[7] for details and examples. +credential.interactive:: + By default, Git and any configured credential helpers will ask for + user input when new credentials are required. Many of these helpers + will succeed based on stored credentials if those credentials are + still valid. To avoid the possibility of user interactivity from + Git, set `credential.interactive=false`. Some credential helpers + respect this option as well. + credential.useHttpPath:: When acquiring credentials, consider the "path" component of an http or https URL to be important. Defaults to false. See diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.txt index 190bda17e5..45f3fe855c 100644 --- a/Documentation/config/diff.txt +++ b/Documentation/config/diff.txt @@ -1,18 +1,25 @@ -diff.autoRefreshIndex:: - When using 'git diff' to compare with work tree +`diff.autoRefreshIndex`:: + When using `git diff` to compare with work tree files, do not consider stat-only changes as changed. Instead, silently run `git update-index --refresh` to update the cached stat information for paths whose contents in the work tree match the contents in the - index. This option defaults to true. Note that this - affects only 'git diff' Porcelain, and not lower level - 'diff' commands such as 'git diff-files'. + index. This option defaults to `true`. Note that this + affects only `git diff` Porcelain, and not lower level + `diff` commands such as `git diff-files`. -diff.dirstat:: +`diff.dirstat`:: +ifdef::git-diff[] + A comma separated list of `--dirstat` parameters specifying the + default behavior of the `--dirstat` option to `git diff` and friends. +endif::git-diff[] +ifndef::git-diff[] A comma separated list of `--dirstat` parameters specifying the default behavior of the `--dirstat` option to linkgit:git-diff[1] - and friends. The defaults can be overridden on the command line - (using `--dirstat=<param1,param2,...>`). The fallback defaults + and friends. +endif::git-diff[] + The defaults can be overridden on the command line + (using `--dirstat=<param>,...`). The fallback defaults (when not changed by `diff.dirstat`) are `changes,noncumulative,3`. The following parameters are available: + @@ -41,7 +48,7 @@ diff.dirstat:: Note that when using `cumulative`, the sum of the percentages reported may exceed 100%. The default (non-cumulative) behavior can be specified with the `noncumulative` parameter. -<limit>;; +_<limit>_;; An integer parameter specifies a cut-off percent (3% by default). Directories contributing less than this percentage of the changes are not shown in the output. @@ -52,58 +59,58 @@ directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: `files,10,cumulative`. -diff.statNameWidth:: - Limit the width of the filename part in --stat output. If set, applies - to all commands generating --stat output except format-patch. +`diff.statNameWidth`:: + Limit the width of the filename part in `--stat` output. If set, applies + to all commands generating `--stat` output except `format-patch`. -diff.statGraphWidth:: - Limit the width of the graph part in --stat output. If set, applies - to all commands generating --stat output except format-patch. +`diff.statGraphWidth`:: + Limit the width of the graph part in `--stat` output. If set, applies + to all commands generating `--stat` output except `format-patch`. -diff.context:: - Generate diffs with <n> lines of context instead of the default - of 3. This value is overridden by the -U option. +`diff.context`:: + Generate diffs with _<n>_ lines of context instead of the default + of 3. This value is overridden by the `-U` option. -diff.interHunkContext:: +`diff.interHunkContext`:: Show the context between diff hunks, up to the specified number of lines, thereby fusing the hunks that are close to each other. This value serves as the default for the `--inter-hunk-context` command line option. -diff.external:: +`diff.external`:: If this config variable is set, diff generation is not performed using the internal diff machinery, but using the - given command. Can be overridden with the `GIT_EXTERNAL_DIFF' + given command. Can be overridden with the `GIT_EXTERNAL_DIFF` environment variable. The command is called with parameters as described under "git Diffs" in linkgit:git[1]. Note: if you want to use an external diff program only on a subset of your files, you might want to use linkgit:gitattributes[5] instead. -diff.trustExitCode:: - If this boolean value is set to true then the +`diff.trustExitCode`:: + If this boolean value is set to `true` then the `diff.external` command is expected to return exit code 0 if it considers the input files to be equal or 1 if it - considers them to be different, like `diff(1)`. - If it is set to false, which is the default, then the command - is expected to return exit code 0 regardless of equality. + considers them to be different, like `diff`(1). + If it is set to `false`, which is the default, then the command + is expected to return exit code `0` regardless of equality. Any other exit code causes Git to report a fatal error. -diff.ignoreSubmodules:: - Sets the default value of --ignore-submodules. Note that this - affects only 'git diff' Porcelain, and not lower level 'diff' - commands such as 'git diff-files'. 'git checkout' - and 'git switch' also honor +`diff.ignoreSubmodules`:: + Sets the default value of `--ignore-submodules`. Note that this + affects only `git diff` Porcelain, and not lower level `diff` + commands such as `git diff-files`. `git checkout` + and `git switch` also honor this setting when reporting uncommitted changes. Setting it to - 'all' disables the submodule summary normally shown by 'git commit' - and 'git status' when `status.submoduleSummary` is set unless it is - overridden by using the --ignore-submodules command-line option. - The 'git submodule' commands are not affected by this setting. + `all` disables the submodule summary normally shown by `git commit` + and `git status` when `status.submoduleSummary` is set unless it is + overridden by using the `--ignore-submodules` command-line option. + The `git submodule` commands are not affected by this setting. By default this is set to untracked so that any untracked submodules are ignored. -diff.mnemonicPrefix:: - If set, 'git diff' uses a prefix pair that is different from the - standard "a/" and "b/" depending on what is being compared. When +`diff.mnemonicPrefix`:: + If set, `git diff` uses a prefix pair that is different from the + standard `a/` and `b/` depending on what is being compared. When this configuration is in effect, reverse diff output also swaps the order of the prefixes: `git diff`;; @@ -112,111 +119,117 @@ diff.mnemonicPrefix:: compares a (c)ommit and the (w)ork tree; `git diff --cached`;; compares a (c)ommit and the (i)ndex; -`git diff HEAD:file1 file2`;; +`git diff HEAD:<file1> <file2>`;; compares an (o)bject and a (w)ork tree entity; -`git diff --no-index a b`;; - compares two non-git things (1) and (2). +`git diff --no-index <a> <b>`;; + compares two non-git things _<a>_ and _<b>_. -diff.noPrefix:: - If set, 'git diff' does not show any source or destination prefix. +`diff.noPrefix`:: + If set, `git diff` does not show any source or destination prefix. -diff.srcPrefix:: - If set, 'git diff' uses this source prefix. Defaults to "a/". +`diff.srcPrefix`:: + If set, `git diff` uses this source prefix. Defaults to `a/`. -diff.dstPrefix:: - If set, 'git diff' uses this destination prefix. Defaults to "b/". +`diff.dstPrefix`:: + If set, `git diff` uses this destination prefix. Defaults to `b/`. -diff.relative:: - If set to 'true', 'git diff' does not show changes outside of the directory +`diff.relative`:: + If set to `true`, `git diff` does not show changes outside of the directory and show pathnames relative to the current directory. -diff.orderFile:: +`diff.orderFile`:: File indicating how to order files within a diff. - See the '-O' option to linkgit:git-diff[1] for details. +ifdef::git-diff[] + See the `-O` option for details. +endif::git-diff[] +ifndef::git-diff[] + See the `-O` option to linkgit:git-diff[1] for details. +endif::git-diff[] If `diff.orderFile` is a relative pathname, it is treated as relative to the top of the working tree. -diff.renameLimit:: +`diff.renameLimit`:: The number of files to consider in the exhaustive portion of - copy/rename detection; equivalent to the 'git diff' option + copy/rename detection; equivalent to the `git diff` option `-l`. If not set, the default value is currently 1000. This setting has no effect if rename detection is turned off. -diff.renames:: - Whether and how Git detects renames. If set to "false", - rename detection is disabled. If set to "true", basic rename - detection is enabled. If set to "copies" or "copy", Git will - detect copies, as well. Defaults to true. Note that this - affects only 'git diff' Porcelain like linkgit:git-diff[1] and +`diff.renames`:: + Whether and how Git detects renames. If set to `false`, + rename detection is disabled. If set to `true`, basic rename + detection is enabled. If set to `copies` or `copy`, Git will + detect copies, as well. Defaults to `true`. Note that this + affects only `git diff` Porcelain like linkgit:git-diff[1] and linkgit:git-log[1], and not lower level commands such as linkgit:git-diff-files[1]. -diff.suppressBlankEmpty:: +`diff.suppressBlankEmpty`:: A boolean to inhibit the standard behavior of printing a space - before each empty output line. Defaults to false. + before each empty output line. Defaults to `false`. -diff.submodule:: +`diff.submodule`:: Specify the format in which differences in submodules are - shown. The "short" format just shows the names of the commits - at the beginning and end of the range. The "log" format lists + shown. The `short` format just shows the names of the commits + at the beginning and end of the range. The `log` format lists the commits in the range like linkgit:git-submodule[1] `summary` - does. The "diff" format shows an inline diff of the changed - contents of the submodule. Defaults to "short". + does. The `diff` format shows an inline diff of the changed + contents of the submodule. Defaults to `short`. -diff.wordRegex:: +`diff.wordRegex`:: A POSIX Extended Regular Expression used to determine what is a "word" when performing word-by-word difference calculations. Character sequences that match the regular expression are "words", all other characters are *ignorable* whitespace. -diff.<driver>.command:: +`diff.<driver>.command`:: The custom diff driver command. See linkgit:gitattributes[5] for details. -diff.<driver>.trustExitCode:: - If this boolean value is set to true then the +`diff.<driver>.trustExitCode`:: + If this boolean value is set to `true` then the `diff.<driver>.command` command is expected to return exit code 0 if it considers the input files to be equal or 1 if it - considers them to be different, like `diff(1)`. - If it is set to false, which is the default, then the command + considers them to be different, like `diff`(1). + If it is set to `false`, which is the default, then the command is expected to return exit code 0 regardless of equality. Any other exit code causes Git to report a fatal error. -diff.<driver>.xfuncname:: +`diff.<driver>.xfuncname`:: The regular expression that the diff driver should use to recognize the hunk header. A built-in pattern may also be used. See linkgit:gitattributes[5] for details. -diff.<driver>.binary:: - Set this option to true to make the diff driver treat files as +`diff.<driver>.binary`:: + Set this option to `true` to make the diff driver treat files as binary. See linkgit:gitattributes[5] for details. -diff.<driver>.textconv:: +`diff.<driver>.textconv`:: The command that the diff driver should call to generate the text-converted version of a file. The result of the conversion is used to generate a human-readable diff. See linkgit:gitattributes[5] for details. -diff.<driver>.wordRegex:: +`diff.<driver>.wordRegex`:: The regular expression that the diff driver should use to split words in a line. See linkgit:gitattributes[5] for details. -diff.<driver>.cachetextconv:: - Set this option to true to make the diff driver cache the text +`diff.<driver>.cachetextconv`:: + Set this option to `true` to make the diff driver cache the text conversion outputs. See linkgit:gitattributes[5] for details. include::../mergetools-diff.txt[] -diff.indentHeuristic:: +`diff.indentHeuristic`:: Set this option to `false` to disable the default heuristics that shift diff hunk boundaries to make patches easier to read. -diff.algorithm:: +`diff.algorithm`:: Choose a diff algorithm. The variants are as follows: + -- -`default`, `myers`;; +`default`;; +`myers`;; The basic greedy diff algorithm. Currently, this is the default. `minimal`;; Spend extra time to make sure the smallest possible diff is @@ -229,7 +242,7 @@ diff.algorithm:: -- + -diff.wsErrorHighlight:: +`diff.wsErrorHighlight`:: Highlight whitespace errors in the `context`, `old` or `new` lines of the diff. Multiple values are separated by comma, `none` resets previous values, `default` reset the list to @@ -238,14 +251,19 @@ diff.wsErrorHighlight:: The command line option `--ws-error-highlight=<kind>` overrides this setting. -diff.colorMoved:: - If set to either a valid `<mode>` or a true value, moved lines - in a diff are colored differently, for details of valid modes - see '--color-moved' in linkgit:git-diff[1]. If simply set to - true the default color mode will be used. When set to false, - moved lines are not colored. - -diff.colorMovedWS:: +`diff.colorMoved`:: + If set to either a valid _<mode>_ or a `true` value, moved lines + in a diff are colored differently. +ifdef::git-diff[] + For details of valid modes see `--color-moved`. +endif::git-diff[] +ifndef::git-diff[] + For details of valid modes see `--color-moved` in linkgit:git-diff[1]. +endif::git-diff[] + If simply set to `true` the default color mode will be used. When + set to `false`, moved lines are not colored. + +`diff.colorMovedWS`:: When moved lines are colored using e.g. the `diff.colorMoved` setting, - this option controls the `<mode>` how spaces are treated. - For details of valid modes see '--color-moved-ws' in linkgit:git-diff[1]. + this option controls the mode how spaces are treated. + For details of valid modes see `--color-moved-ws` in linkgit:git-diff[1]. diff --git a/Documentation/config/extensions.txt b/Documentation/config/extensions.txt index 38dce3df35..5cb4721a0e 100644 --- a/Documentation/config/extensions.txt +++ b/Documentation/config/extensions.txt @@ -1,17 +1,13 @@ -extensions.objectFormat:: - Specify the hash algorithm to use. The acceptable values are `sha1` and - `sha256`. If not specified, `sha1` is assumed. It is an error to specify - this key unless `core.repositoryFormatVersion` is 1. +extensions.*:: + Unless otherwise stated, is an error to specify an extension if + `core.repositoryFormatVersion` is not `1`. See + linkgit:gitrepository-layout[5]. + -Note that this setting should only be set by linkgit:git-init[1] or -linkgit:git-clone[1]. Trying to change it after initialization will not -work and will produce hard-to-diagnose issues. - -extensions.compatObjectFormat:: - - Specify a compatitbility hash algorithm to use. The acceptable values +-- +compatObjectFormat:: + Specify a compatibility hash algorithm to use. The acceptable values are `sha1` and `sha256`. The value specified must be different from the - value of extensions.objectFormat. This allows client level + value of `extensions.objectFormat`. This allows client level interoperability between git repositories whose objectFormat matches this compatObjectFormat. In particular when fully implemented the pushes and pulls from a repository in whose objectFormat matches @@ -19,18 +15,61 @@ extensions.compatObjectFormat:: compatObjectFormat in addition to oids encoded with objectFormat to locally specify objects. -extensions.refStorage:: +noop:: + This extension does not change git's behavior at all. It is useful only + for testing format-1 compatibility. ++ +For historical reasons, this extension is respected regardless of the +`core.repositoryFormatVersion` setting. + +noop-v1:: + This extension does not change git's behavior at all. It is useful only + for testing format-1 compatibility. + +objectFormat:: + Specify the hash algorithm to use. The acceptable values are `sha1` and + `sha256`. If not specified, `sha1` is assumed. ++ +Note that this setting should only be set by linkgit:git-init[1] or +linkgit:git-clone[1]. Trying to change it after initialization will not +work and will produce hard-to-diagnose issues. + +partialClone:: + When enabled, indicates that the repo was created with a partial clone + (or later performed a partial fetch) and that the remote may have + omitted sending certain unwanted objects. Such a remote is called a + "promisor remote" and it promises that all such omitted objects can + be fetched from it in the future. ++ +The value of this key is the name of the promisor remote. ++ +For historical reasons, this extension is respected regardless of the +`core.repositoryFormatVersion` setting. + +preciousObjects:: + If enabled, indicates that objects in the repository MUST NOT be deleted + (e.g., by `git-prune` or `git repack -d`). ++ +For historical reasons, this extension is respected regardless of the +`core.repositoryFormatVersion` setting. + +refStorage:: Specify the ref storage format to use. The acceptable values are: + include::../ref-storage-format.txt[] -+ -It is an error to specify this key unless `core.repositoryFormatVersion` is 1. + + Note that this setting should only be set by linkgit:git-init[1] or linkgit:git-clone[1]. Trying to change it after initialization will not work and will produce hard-to-diagnose issues. -extensions.worktreeConfig:: +relativeWorktrees:: + If enabled, indicates at least one worktree has been linked with + relative paths. Automatically set if a worktree has been created or + repaired with either the `--relative-paths` option or with the + `worktree.useRelativePaths` config set to `true`. + +worktreeConfig:: If enabled, then worktrees will load config settings from the `$GIT_DIR/config.worktree` file in addition to the `$GIT_COMMON_DIR/config` file. Note that `$GIT_COMMON_DIR` and @@ -40,7 +79,7 @@ extensions.worktreeConfig:: `config.worktree` file will override settings from any other config files. + -When enabling `extensions.worktreeConfig`, you must be careful to move +When enabling this extension, you must be careful to move certain values from the common config file to the main working tree's `config.worktree` file, if present: + @@ -48,15 +87,17 @@ certain values from the common config file to the main working tree's `$GIT_COMMON_DIR/config.worktree`. * If `core.bare` is true, then it must be moved from `$GIT_COMMON_DIR/config` to `$GIT_COMMON_DIR/config.worktree`. + + It may also be beneficial to adjust the locations of `core.sparseCheckout` and `core.sparseCheckoutCone` depending on your desire for customizable sparse-checkout settings for each worktree. By default, the `git -sparse-checkout` builtin enables `extensions.worktreeConfig`, assigns +sparse-checkout` builtin enables this extension, assigns these config values on a per-worktree basis, and uses the `$GIT_DIR/info/sparse-checkout` file to specify the sparsity for each worktree independently. See linkgit:git-sparse-checkout[1] for more details. + -For historical reasons, `extensions.worktreeConfig` is respected -regardless of the `core.repositoryFormatVersion` setting. +For historical reasons, this extension is respected regardless of the +`core.repositoryFormatVersion` setting. +-- diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt index 664a3c2874..21d56db279 100644 --- a/Documentation/config/gc.txt +++ b/Documentation/config/gc.txt @@ -40,7 +40,8 @@ use, it'll affect how the auto pack limit works. gc.autoDetach:: Make `git gc --auto` return immediately and run in the background - if the system supports it. Default is true. + if the system supports it. Default is true. This config variable acts + as a fallback in case `maintenance.autoDetach` is not set. gc.bigPackThreshold:: If non-zero, all non-cruft packs larger than this limit are kept @@ -162,7 +163,7 @@ gc.repackFilterTo:: containing the filtered out objects. **WARNING:** The specified location should be accessible, using for example the Git alternates mechanism, otherwise the repo could be - considered corrupt by Git as it migh not be able to access the + considered corrupt by Git as it might not be able to access the objects in that packfile. See the `--filter-to=<dir>` option of linkgit:git-repack[1] and the `objects/info/alternates` section of linkgit:gitrepository-layout[5]. diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt index 162b33fc52..a14371b5c9 100644 --- a/Documentation/config/http.txt +++ b/Documentation/config/http.txt @@ -5,8 +5,8 @@ http.proxy:: proxy string with a user name but no password, in which case git will attempt to acquire one in the same way it does for other credentials. See linkgit:gitcredentials[7] for more information. The syntax thus is - '[protocol://][user[:password]@]proxyhost[:port]'. This can be overridden - on a per-remote basis; see remote.<name>.proxy + '[protocol://][user[:password]@]proxyhost[:port][/path]'. This can be + overridden on a per-remote basis; see remote.<name>.proxy + Any proxy, however configured, must be completely transparent and must not modify, transform, or buffer the request or response in any way. Proxies which diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt index af03acdbcb..e45b2a8121 100644 --- a/Documentation/config/init.txt +++ b/Documentation/config/init.txt @@ -8,3 +8,13 @@ endif::[] `init.defaultBranch`:: Allows overriding the default branch name e.g. when initializing a new repository. +`init.defaultObjectFormat`:: + Allows overriding the default object format for new repositories. See + `--object-format=` in linkgit:git-init[1]. Both the command line option + and the `GIT_DEFAULT_HASH` environment variable take precedence over + this config. +`init.defaultRefFormat`:: + Allows overriding the default ref storage format for new repositories. + See `--ref-format=` in linkgit:git-init[1]. Both the command line + option and the `GIT_DEFAULT_REF_FORMAT` environment variable take + precedence over this config. diff --git a/Documentation/config/maintenance.txt b/Documentation/config/maintenance.txt index 69a4f05153..72a9d6cf81 100644 --- a/Documentation/config/maintenance.txt +++ b/Documentation/config/maintenance.txt @@ -3,6 +3,17 @@ maintenance.auto:: `git maintenance run --auto` after doing their normal work. Defaults to true. +maintenance.autoDetach:: + Many Git commands trigger automatic maintenance after they have + written data into the repository. This boolean config option + controls whether this automatic maintenance shall happen in the + foreground or whether the maintenance process shall detach and + continue to run in the background. ++ +If unset, the value of `gc.autoDetach` is used as a fallback. Defaults +to true if both are unset, meaning that the maintenance process will +detach. + maintenance.strategy:: This string config option provides a way to specify one of a few recommended schedules for background maintenance. This only affects diff --git a/Documentation/config/reftable.txt b/Documentation/config/reftable.txt index 0515727977..57087803a5 100644 --- a/Documentation/config/reftable.txt +++ b/Documentation/config/reftable.txt @@ -46,3 +46,11 @@ reftable.geometricFactor:: By default, the geometric sequence uses a factor of 2, meaning that for any table, the next-biggest table must at least be twice as big. A maximum factor of 256 is supported. + +reftable.lockTimeout:: + Whenever the reftable backend appends a new table to the stack, it has + to lock the central "tables.list" file before updating it. This config + controls how long the process will wait to acquire the lock in case + another process has already acquired it. Value 0 means not to retry at + all; -1 means to try indefinitely. Default is 100 (i.e., retry for + 100ms). diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt index 8efc53e836..6d8b7d6c63 100644 --- a/Documentation/config/remote.txt +++ b/Documentation/config/remote.txt @@ -42,14 +42,15 @@ remote.<name>.mirror:: as if the `--mirror` option was given on the command line. remote.<name>.skipDefaultUpdate:: - If true, this remote will be skipped by default when updating - using linkgit:git-fetch[1] or the `update` subcommand of - linkgit:git-remote[1]. + A deprecated synonym to `remote.<name>.skipFetchAll` (if + both are set in the configuration files with different + values, the value of the last occurrence will be used). remote.<name>.skipFetchAll:: - If true, this remote will be skipped by default when updating - using linkgit:git-fetch[1] or the `update` subcommand of - linkgit:git-remote[1]. + If true, this remote will be skipped when updating + using linkgit:git-fetch[1], the `update` subcommand of + linkgit:git-remote[1], and ignored by the prefetch task + of `git maintenance`. remote.<name>.receivepack:: The default program to execute on the remote side when pushing. See @@ -95,3 +96,13 @@ remote.<name>.partialclonefilter:: Changing or clearing this value will only affect fetches for new commits. To fetch associated objects for commits already present in the local object database, use the `--refetch` option of linkgit:git-fetch[1]. + +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`). diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.txt index 6a869d67eb..5ffcfc9f2a 100644 --- a/Documentation/config/sendemail.txt +++ b/Documentation/config/sendemail.txt @@ -30,6 +30,21 @@ sendemail.confirm:: in the linkgit:git-send-email[1] documentation for the meaning of these values. +sendemail.mailmap:: + If true, makes linkgit:git-send-email[1] assume `--mailmap`, + otherwise assume `--no-mailmap`. False by default. + +sendemail.mailmap.file:: + The location of a linkgit:git-send-email[1] specific augmenting + mailmap file. The default mailmap and `mailmap.file` are loaded + first. Thus, entries in this file take precedence over entries in + the default mailmap locations. See linkgit:gitmailmap[5]. + +sendemail.mailmap.blob:: + Like `sendemail.mailmap.file`, but consider the value as a reference + to a blob in the repository. Entries in `sendemail.mailmap.file` + take precedence over entries here. See linkgit:gitmailmap[5]. + sendemail.aliasesFile:: To avoid typing long email addresses, point this to one or more email aliases files. You must also supply `sendemail.aliasFileType`. diff --git a/Documentation/config/uploadpack.txt b/Documentation/config/uploadpack.txt index 16264d82a7..0e1dda944a 100644 --- a/Documentation/config/uploadpack.txt +++ b/Documentation/config/uploadpack.txt @@ -25,7 +25,11 @@ uploadpack.allowReachableSHA1InWant:: uploadpack.allowAnySHA1InWant:: Allow `upload-pack` to accept a fetch request that asks for any object at all. - Defaults to `false`. + It implies `uploadpack.allowTipSHA1InWant` and + `uploadpack.allowReachableSHA1InWant`. If set to `true` it will + enable both of them, it set to `false` it will disable both of + them. + By default not set. uploadpack.keepAlive:: When `upload-pack` has started `pack-objects`, there may be a diff --git a/Documentation/config/worktree.txt b/Documentation/config/worktree.txt index 048e349482..5e35c7d018 100644 --- a/Documentation/config/worktree.txt +++ b/Documentation/config/worktree.txt @@ -7,3 +7,13 @@ worktree.guessRemote:: such a branch exists, it is checked out and set as "upstream" for the new branch. If no such match can be found, it falls back to creating a new branch from the current HEAD. + +worktree.useRelativePaths:: + Link worktrees using relative paths (when "true") or absolute + paths (when "false"). This is particularly useful for setups + where the repository and worktrees may be moved between + different locations or environments. Defaults to "false". ++ +Note that setting `worktree.useRelativePaths` to "true" implies enabling the +`extension.relativeWorktrees` config (see linkgit:git-config[1]), +thus making it incompatible with older versions of Git. diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index a3ae8747a2..c72fb37986 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -1,25 +1,25 @@ Raw output format ----------------- -The raw output format from "git-diff-index", "git-diff-tree", -"git-diff-files" and "git diff --raw" are very similar. +The raw output format from `git-diff-index`, `git-diff-tree`, +`git-diff-files` and `git diff --raw` are very similar. These commands all compare two sets of things; what is compared differs: -git-diff-index <tree-ish>:: - compares the <tree-ish> and the files on the filesystem. +`git-diff-index <tree-ish>`:: + compares the _<tree-ish>_ and the files on the filesystem. -git-diff-index --cached <tree-ish>:: - compares the <tree-ish> and the index. +`git-diff-index --cached <tree-ish>`:: + compares the _<tree-ish>_ and the index. -git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]:: +`git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]`:: compares the trees named by the two arguments. -git-diff-files [<pattern>...]:: +`git-diff-files [<pattern>...]`:: compares the index and the files on the filesystem. -The "git-diff-tree" command begins its output by printing the hash of +The `git-diff-tree` command begins its output by printing the hash of what is being compared. After that, all the commands print one output line per changed file. @@ -54,19 +54,19 @@ That is, from the left to the right: Possible status letters are: -- A: addition of a file -- C: copy of a file into a new one -- D: deletion of a file -- M: modification of the contents or mode of a file -- R: renaming of a file -- T: change in the type of the file (regular file, symbolic link or submodule) -- U: file is unmerged (you must complete the merge before it can +- `A`: addition of a file +- `C`: copy of a file into a new one +- `D`: deletion of a file +- `M`: modification of the contents or mode of a file +- `R`: renaming of a file +- `T`: change in the type of the file (regular file, symbolic link or submodule) +- `U`: file is unmerged (you must complete the merge before it can be committed) -- X: "unknown" change type (most probably a bug, please report it) +- `X`: "unknown" change type (most probably a bug, please report it) -Status letters C and R are always followed by a score (denoting the +Status letters `C` and `R` are always followed by a score (denoting the percentage of similarity between the source and target of the move or -copy). Status letter M may be followed by a score (denoting the +copy). Status letter `M` may be followed by a score (denoting the percentage of dissimilarity) for file rewrites. The sha1 for "dst" is shown as all 0's if a file on the filesystem @@ -86,7 +86,7 @@ verbatim and the line is terminated by a NUL byte. diff format for merges ---------------------- -"git-diff-tree", "git-diff-files" and "git-diff --raw" +`git-diff-tree`, `git-diff-files` and `git-diff --raw` can take `-c` or `--cc` option to generate diff output also for merge commits. The output differs from the format described above in the following way: @@ -128,7 +128,7 @@ other diff formats ------------------ The `--summary` option describes newly added, deleted, renamed and -copied files. The `--stat` option adds diffstat(1) graph to the +copied files. The `--stat` option adds `diffstat`(1) graph to the output. These options can be combined with other options, such as `-p`, and are meant for human consumption. diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt index 4b5aa5c2e0..e5c813c96f 100644 --- a/Documentation/diff-generate-patch.txt +++ b/Documentation/diff-generate-patch.txt @@ -14,7 +14,7 @@ You can customize the creation of patch text via the `GIT_EXTERNAL_DIFF` and the `GIT_DIFF_OPTS` environment variables (see linkgit:git[1]), and the `diff` attribute (see linkgit:gitattributes[5]). -What the -p option produces is slightly different from the traditional +What the `-p` option produces is slightly different from the traditional diff format: 1. It is preceded by a "git diff" header that looks like this: @@ -30,20 +30,21 @@ name of the source file of the rename/copy and the name of the file that the rename/copy produces, respectively. 2. It is followed by one or more extended header lines: - - old mode <mode> - new mode <mode> - deleted file mode <mode> - new file mode <mode> - copy from <path> - copy to <path> - rename from <path> - rename to <path> - similarity index <number> - dissimilarity index <number> - index <hash>..<hash> <mode> + -File modes are printed as 6-digit octal numbers including the file type +[synopsis] +old mode <mode> +new mode <mode> +deleted file mode <mode> +new file mode <mode> +copy from <path> +copy to <path> +rename from <path> +rename to <path> +similarity index <number> +dissimilarity index <number> +index <hash>..<hash> <mode> ++ +File modes _<mode>_ are printed as 6-digit octal numbers including the file type and file permission bits. + Path names in extended headers do not include the `a/` and `b/` prefixes. @@ -56,7 +57,7 @@ files, while 100% dissimilarity means that no line from the old file made it into the new one. + The index line includes the blob object names before and after the change. -The <mode> is included if the file mode does not change; otherwise, +The _<mode>_ is included if the file mode does not change; otherwise, separate lines indicate the old and the new mode. 3. Pathnames with "unusual" characters are quoted as explained for @@ -134,17 +135,18 @@ or like this (when the `--cc` option is used): 2. It is followed by one or more extended header lines (this example shows a merge with two parents): - - index <hash>,<hash>..<hash> - mode <mode>,<mode>..<mode> - new file mode <mode> - deleted file mode <mode>,<mode> ++ +[synopsis] +index <hash>,<hash>..<hash> +mode <mode>,<mode>`..`<mode> +new file mode <mode> +deleted file mode <mode>,<mode> + The `mode <mode>,<mode>..<mode>` line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected content movement (renames and copying detection) are designed to work with the diff of two -<tree-ish> and are not used by combined diff format. +_<tree-ish>_ and are not used by combined diff format. 3. It is followed by a two-line from-file/to-file header: diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index cd0b81adbb..640eb6e7db 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -19,16 +19,16 @@ ifdef::git-format-patch[] endif::git-format-patch[] ifndef::git-format-patch[] --p:: --u:: ---patch:: +`-p`:: +`-u`:: +`--patch`:: Generate patch (see <<generate_patch_text_with_p>>). ifdef::git-diff[] This is the default. endif::git-diff[] --s:: ---no-patch:: +`-s`:: +`--no-patch`:: Suppress all output from the diff machinery. Useful for commands like `git show` that show the patch by default to squelch their output, or to cancel the effect of options like @@ -39,28 +39,28 @@ endif::git-format-patch[] ifdef::git-log[] -m:: Show diffs for merge commits in the default format. This is - similar to '--diff-merges=on', except `-m` will + similar to `--diff-merges=on`, except `-m` will produce no output unless `-p` is given as well. -c:: Produce combined diff output for merge commits. - Shortcut for '--diff-merges=combined -p'. + Shortcut for `--diff-merges=combined -p`. --cc:: Produce dense combined diff output for merge commits. - Shortcut for '--diff-merges=dense-combined -p'. + Shortcut for `--diff-merges=dense-combined -p`. --dd:: Produce diff with respect to first parent for both merge and regular commits. - Shortcut for '--diff-merges=first-parent -p'. + Shortcut for `--diff-merges=first-parent -p`. --remerge-diff:: Produce remerge-diff output for merge commits. - Shortcut for '--diff-merges=remerge -p'. + Shortcut for `--diff-merges=remerge -p`. --no-diff-merges:: - Synonym for '--diff-merges=off'. + Synonym for `--diff-merges=off`. --diff-merges=<format>:: Specify diff format to be used for merge commits. Default is @@ -73,33 +73,33 @@ The following formats are supported: off, none:: Disable output of diffs for merge commits. Useful to override implied value. -+ + on, m:: Make diff output for merge commits to be shown in the default format. The default format can be changed using `log.diffMerges` configuration variable, whose default value is `separate`. -+ + first-parent, 1:: Show full diff with respect to first parent. This is the same format as `--patch` produces for non-merge commits. -+ + separate:: Show full diff with respect to each of parents. Separate log entry and diff is generated for each parent. -+ + combined, c:: Show differences from each of the parents to the merge result simultaneously instead of showing pairwise diff between a parent and the result one at a time. Furthermore, it lists only files which were modified from all parents. -+ + dense-combined, cc:: Further compress output produced by `--diff-merges=combined` by omitting uninteresting hunks whose contents in the parents have only two variants and the merge result picks one of them without modification. -+ + remerge, r:: Remerge two-parent merge commits to create a temporary tree object--potentially containing files with conflict markers @@ -112,33 +112,33 @@ documented). -- --combined-all-paths:: - This flag causes combined diffs (used for merge commits) to + Cause combined diffs (used for merge commits) to list the name of the file from all parents. It thus only has effect when `--diff-merges=[dense-]combined` is in use, and is likely only useful if filename changes are detected (i.e. when either rename or copy detection have been requested). endif::git-log[] --U<n>:: ---unified=<n>:: - Generate diffs with <n> lines of context instead of +`-U<n>`:: +`--unified=<n>`:: + Generate diffs with _<n>_ lines of context instead of the usual three. ifndef::git-format-patch[] Implies `--patch`. endif::git-format-patch[] ---output=<file>:: +`--output=<file>`:: Output to a specific file instead of stdout. ---output-indicator-new=<char>:: ---output-indicator-old=<char>:: ---output-indicator-context=<char>:: +`--output-indicator-new=<char>`:: +`--output-indicator-old=<char>`:: +`--output-indicator-context=<char>`:: Specify the character used to indicate new, old or context - lines in the generated patch. Normally they are '+', '-' and + lines in the generated patch. Normally they are `+`, `-` and ' ' respectively. ifndef::git-format-patch[] ---raw:: +`--raw`:: ifndef::git-log[] Generate the diff in raw format. ifdef::git-diff-core[] @@ -155,54 +155,55 @@ endif::git-log[] endif::git-format-patch[] ifndef::git-format-patch[] ---patch-with-raw:: +`--patch-with-raw`:: Synonym for `-p --raw`. endif::git-format-patch[] ifdef::git-log[] --t:: +`-t`:: Show the tree objects in the diff output. endif::git-log[] ---indent-heuristic:: +`--indent-heuristic`:: Enable the heuristic that shifts diff hunk boundaries to make patches easier to read. This is the default. ---no-indent-heuristic:: +`--no-indent-heuristic`:: Disable the indent heuristic. ---minimal:: +`--minimal`:: Spend extra time to make sure the smallest possible diff is produced. ---patience:: +`--patience`:: Generate a diff using the "patience diff" algorithm. ---histogram:: +`--histogram`:: Generate a diff using the "histogram diff" algorithm. ---anchored=<text>:: +`--anchored=<text>`:: Generate a diff using the "anchored diff" algorithm. + This option may be specified more than once. + If a line exists in both the source and destination, exists only once, -and starts with this text, this algorithm attempts to prevent it from +and starts with _<text>_, this algorithm attempts to prevent it from appearing as a deletion or addition in the output. It uses the "patience diff" algorithm internally. ---diff-algorithm={patience|minimal|histogram|myers}:: +`--diff-algorithm=(patience|minimal|histogram|myers)`:: Choose a diff algorithm. The variants are as follows: + -- -`default`, `myers`;; + `default`;; + `myers`;; The basic greedy diff algorithm. Currently, this is the default. -`minimal`;; + `minimal`;; Spend extra time to make sure the smallest possible diff is produced. -`patience`;; + `patience`;; Use "patience diff" algorithm when generating patches. -`histogram`;; + `histogram`;; This algorithm extends the patience algorithm to "support low-occurrence common elements". -- @@ -211,47 +212,47 @@ For instance, if you configured the `diff.algorithm` variable to a non-default value and want to use the default one, then you have to use `--diff-algorithm=default` option. ---stat[=<width>[,<name-width>[,<count>]]]:: +`--stat[=<width>[,<name-width>[,<count>]]]`:: Generate a diffstat. By default, as much space as necessary will be used for the filename part, and the rest for the graph part. Maximum width defaults to terminal width, or 80 columns if not connected to a terminal, and can be overridden by - `<width>`. The width of the filename part can be limited by - giving another width `<name-width>` after a comma or by setting - `diff.statNameWidth=<width>`. The width of the graph part can be - limited by using `--stat-graph-width=<width>` or by setting - `diff.statGraphWidth=<width>`. Using `--stat` or + _<width>_. The width of the filename part can be limited by + giving another width _<name-width>_ after a comma or by setting + `diff.statNameWidth=<name-width>`. The width of the graph part can be + limited by using `--stat-graph-width=<graph-width>` or by setting + `diff.statGraphWidth=<graph-width>`. Using `--stat` or `--stat-graph-width` affects all commands generating a stat graph, while setting `diff.statNameWidth` or `diff.statGraphWidth` does not affect `git format-patch`. - By giving a third parameter `<count>`, you can limit the output to - the first `<count>` lines, followed by `...` if there are more. + By giving a third parameter _<count>_, you can limit the output to + the first _<count>_ lines, followed by `...` if there are more. + These parameters can also be set individually with `--stat-width=<width>`, `--stat-name-width=<name-width>` and `--stat-count=<count>`. ---compact-summary:: +`--compact-summary`:: Output a condensed summary of extended header information such - as file creations or deletions ("new" or "gone", optionally "+l" - if it's a symlink) and mode changes ("+x" or "-x" for adding + as file creations or deletions ("new" or "gone", optionally `+l` + if it's a symlink) and mode changes (`+x` or `-x` for adding or removing executable bit respectively) in diffstat. The information is put between the filename part and the graph part. Implies `--stat`. ---numstat:: +`--numstat`:: Similar to `--stat`, but shows number of added and deleted lines in decimal notation and pathname without abbreviation, to make it more machine friendly. For binary files, outputs two `-` instead of saying `0 0`. ---shortstat:: +`--shortstat`:: Output only the last line of the `--stat` format containing total number of modified files, as well as number of added and deleted lines. --X[<param1,param2,...>]:: ---dirstat[=<param1,param2,...>]:: +`-X [<param>,...]`:: +`--dirstat[=<param>,...]`:: Output the distribution of relative amount of changes for each sub-directory. The behavior of `--dirstat` can be customized by passing it a comma separated list of parameters. @@ -284,7 +285,7 @@ These parameters can also be set individually with `--stat-width=<width>`, Note that when using `cumulative`, the sum of the percentages reported may exceed 100%. The default (non-cumulative) behavior can be specified with the `noncumulative` parameter. -<limit>;; +_<limit>_;; An integer parameter specifies a cut-off percent (3% by default). Directories contributing less than this percentage of the changes are not shown in the output. @@ -295,29 +296,29 @@ directories with less than 10% of the total amount of changed files, and accumulating child directory counts in the parent directories: `--dirstat=files,10,cumulative`. ---cumulative:: - Synonym for --dirstat=cumulative +`--cumulative`:: + Synonym for `--dirstat=cumulative`. ---dirstat-by-file[=<param1,param2>...]:: - Synonym for --dirstat=files,<param1>,<param2>... +`--dirstat-by-file[=<param>,...]`:: + Synonym for `--dirstat=files,<param>,...`. ---summary:: +`--summary`:: Output a condensed summary of extended header information such as creations, renames and mode changes. ifndef::git-format-patch[] ---patch-with-stat:: +`--patch-with-stat`:: Synonym for `-p --stat`. endif::git-format-patch[] ifndef::git-format-patch[] --z:: +`-z`:: ifdef::git-log[] - Separate the commits with NULs instead of newlines. + Separate the commits with __NUL__s instead of newlines. + Also, when `--raw` or `--numstat` has been given, do not munge -pathnames and use NULs as output field terminators. +pathnames and use __NUL__s as output field terminators. endif::git-log[] ifndef::git-log[] When `--raw`, `--numstat`, `--name-only` or `--name-status` has been @@ -328,89 +329,89 @@ Without this option, pathnames with "unusual" characters are quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). ---name-only:: +`--name-only`:: Show only the name of each changed file in the post-image tree. The file names are often encoded in UTF-8. For more information see the discussion about encoding in the linkgit:git-log[1] manual page. ---name-status:: +`--name-status`:: Show only the name(s) and status of each changed file. See the description of the `--diff-filter` option on what the status letters mean. Just like `--name-only` the file names are often encoded in UTF-8. ---submodule[=<format>]:: +`--submodule[=<format>]`:: Specify how differences in submodules are shown. When specifying - `--submodule=short` the 'short' format is used. This format just + `--submodule=short` the `short` format is used. This format just shows the names of the commits at the beginning and end of the range. - When `--submodule` or `--submodule=log` is specified, the 'log' + When `--submodule` or `--submodule=log` is specified, the `log` format is used. This format lists the commits in the range like linkgit:git-submodule[1] `summary` does. When `--submodule=diff` - is specified, the 'diff' format is used. This format shows an + is specified, the `diff` format is used. This format shows an inline diff of the changes in the submodule contents between the - commit range. Defaults to `diff.submodule` or the 'short' format + commit range. Defaults to `diff.submodule` or the `short` format if the config option is unset. ---color[=<when>]:: +`--color[=<when>]`:: Show colored diff. - `--color` (i.e. without '=<when>') is the same as `--color=always`. - '<when>' can be one of `always`, `never`, or `auto`. + `--color` (i.e. without `=<when>`) is the same as `--color=always`. + _<when>_ can be one of `always`, `never`, or `auto`. ifdef::git-diff[] It can be changed by the `color.ui` and `color.diff` configuration settings. endif::git-diff[] ---no-color:: +`--no-color`:: Turn off colored diff. ifdef::git-diff[] This can be used to override configuration settings. endif::git-diff[] It is the same as `--color=never`. ---color-moved[=<mode>]:: +`--color-moved[=<mode>]`:: Moved lines of code are colored differently. ifdef::git-diff[] It can be changed by the `diff.colorMoved` configuration setting. endif::git-diff[] - The <mode> defaults to 'no' if the option is not given - and to 'zebra' if the option with no mode is given. + The _<mode>_ defaults to `no` if the option is not given + and to `zebra` if the option with no mode is given. The mode must be one of: + -- -no:: +`no`:: Moved lines are not highlighted. -default:: +`default`:: Is a synonym for `zebra`. This may change to a more sensible mode in the future. -plain:: +`plain`:: Any line that is added in one location and was removed - in another location will be colored with 'color.diff.newMoved'. - Similarly 'color.diff.oldMoved' will be used for removed lines + in another location will be colored with `color.diff.newMoved`. + Similarly `color.diff.oldMoved` will be used for removed lines that are added somewhere else in the diff. This mode picks up any moved line, but it is not very useful in a review to determine if a block of code was moved without permutation. -blocks:: +`blocks`:: Blocks of moved text of at least 20 alphanumeric characters are detected greedily. The detected blocks are - painted using either the 'color.diff.{old,new}Moved' color. + painted using either the `color.diff.(old|new)Moved` color. Adjacent blocks cannot be told apart. -zebra:: - Blocks of moved text are detected as in 'blocks' mode. The blocks - are painted using either the 'color.diff.{old,new}Moved' color or - 'color.diff.{old,new}MovedAlternative'. The change between +`zebra`:: + Blocks of moved text are detected as in `blocks` mode. The blocks + are painted using either the `color.diff.(old|new)Moved` color or + `color.diff.(old|new)MovedAlternative`. The change between the two colors indicates that a new block was detected. -dimmed-zebra:: - Similar to 'zebra', but additional dimming of uninteresting parts +`dimmed-zebra`:: + Similar to `zebra`, but additional dimming of uninteresting parts of moved code is performed. The bordering lines of two adjacent blocks are considered interesting, the rest is uninteresting. `dimmed_zebra` is a deprecated synonym. -- ---no-color-moved:: +`--no-color-moved`:: Turn off move detection. This can be used to override configuration settings. It is the same as `--color-moved=no`. ---color-moved-ws=<modes>:: +`--color-moved-ws=<mode>,...`:: This configures how whitespace is ignored when performing the move detection for `--color-moved`. ifdef::git-diff[] @@ -419,63 +420,62 @@ endif::git-diff[] These modes can be given as a comma separated list: + -- -no:: +`no`:: Do not ignore whitespace when performing move detection. -ignore-space-at-eol:: +`ignore-space-at-eol`:: Ignore changes in whitespace at EOL. -ignore-space-change:: +`ignore-space-change`:: Ignore changes in amount of whitespace. This ignores whitespace at line end, and considers all other sequences of one or more whitespace characters to be equivalent. -ignore-all-space:: +`ignore-all-space`:: Ignore whitespace when comparing lines. This ignores differences even if one line has whitespace where the other line has none. -allow-indentation-change:: +`allow-indentation-change`:: Initially ignore any whitespace in the move detection, then group the moved code blocks only into a block if the change in whitespace is the same per line. This is incompatible with the other modes. -- ---no-color-moved-ws:: +`--no-color-moved-ws`:: Do not ignore whitespace when performing move detection. This can be used to override configuration settings. It is the same as `--color-moved-ws=no`. ---word-diff[=<mode>]:: - Show a word diff, using the <mode> to delimit changed words. +`--word-diff[=<mode>]`:: By default, words are delimited by whitespace; see - `--word-diff-regex` below. The <mode> defaults to 'plain', and + `--word-diff-regex` below. The _<mode>_ defaults to `plain`, and must be one of: + -- -color:: +`color`:: Highlight changed words using only colors. Implies `--color`. -plain:: - Show words as `[-removed-]` and `{+added+}`. Makes no +`plain`:: + Show words as ++[-removed-]++ and ++{+added+}++. Makes no attempts to escape the delimiters if they appear in the input, so the output may be ambiguous. -porcelain:: +`porcelain`:: Use a special line-based format intended for script consumption. Added/removed/unchanged runs are printed in the usual unified diff format, starting with a `+`/`-`/` ` character at the beginning of the line and extending to the end of the line. Newlines in the input are represented by a tilde `~` on a line of its own. -none:: +`none`:: Disable word diff again. -- + Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled. ---word-diff-regex=<regex>:: - Use <regex> to decide what a word is, instead of considering +`--word-diff-regex=<regex>`:: + Use _<regex>_ to decide what a word is, instead of considering runs of non-whitespace to be a word. Also implies `--word-diff` unless it was already enabled. + Every non-overlapping match of the -<regex> is considered a word. Anything between these matches is +_<regex>_ is considered a word. Anything between these matches is considered whitespace and ignored(!) for the purposes of finding differences. You may want to append `|[^[:space:]]` to your regular expression to make sure that it matches all non-whitespace characters. @@ -490,20 +490,20 @@ linkgit:gitattributes[5] or linkgit:git-config[1]. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings. ---color-words[=<regex>]:: +`--color-words[=<regex>]`:: Equivalent to `--word-diff=color` plus (if a regex was specified) `--word-diff-regex=<regex>`. endif::git-format-patch[] ---no-renames:: +`--no-renames`:: Turn off rename detection, even when the configuration file gives the default to do so. ---[no-]rename-empty:: +`--[no-]rename-empty`:: Whether to use empty blobs as rename source. ifndef::git-format-patch[] ---check:: +`--check`:: Warn if changes introduce conflict markers or whitespace errors. What are considered whitespace errors is controlled by `core.whitespace` configuration. By default, trailing whitespaces (including @@ -511,9 +511,9 @@ ifndef::git-format-patch[] that is immediately followed by a tab character inside the initial indent of the line are considered whitespace errors. Exits with non-zero status if problems are found. Not compatible - with --exit-code. + with `--exit-code`. ---ws-error-highlight=<kind>:: +`--ws-error-highlight=<kind>`:: Highlight whitespace errors in the `context`, `old` or `new` lines of the diff. Multiple values are separated by comma, `none` resets previous values, `default` reset the list to @@ -525,30 +525,30 @@ ifndef::git-format-patch[] endif::git-format-patch[] ---full-index:: +`--full-index`:: Instead of the first handful of characters, show the full pre- and post-image blob object names on the "index" line when generating patch format output. ---binary:: +`--binary`:: In addition to `--full-index`, output a binary diff that can be applied with `git-apply`. ifndef::git-format-patch[] Implies `--patch`. endif::git-format-patch[] ---abbrev[=<n>]:: +`--abbrev[=<n>]`:: Instead of showing the full 40-byte hexadecimal object name in diff-raw format output and diff-tree header - lines, show the shortest prefix that is at least '<n>' + lines, show the shortest prefix that is at least _<n>_ hexdigits long that uniquely refers the object. In diff-patch output format, `--full-index` takes higher precedence, i.e. if `--full-index` is specified, full blob names will be shown regardless of `--abbrev`. Non default number of digits can be specified with `--abbrev=<n>`. --B[<n>][/<m>]:: ---break-rewrites[=[<n>][/<m>]]:: +`-B[<n>][/<m>]`:: +`--break-rewrites[=[<n>][/<m>]]`:: Break complete rewrite changes into pairs of delete and create. This serves two purposes: + @@ -556,22 +556,22 @@ It affects the way a change that amounts to a total rewrite of a file not as a series of deletion and insertion mixed together with a very few lines that happen to match textually as the context, but as a single deletion of everything old followed by a single insertion of -everything new, and the number `m` controls this aspect of the -B +everything new, and the number _<m>_ controls this aspect of the `-B` option (defaults to 60%). `-B/70%` specifies that less than 30% of the original should remain in the result for Git to consider it a total rewrite (i.e. otherwise the resulting patch will be a series of deletion and insertion mixed together with context lines). + -When used with -M, a totally-rewritten file is also considered as the -source of a rename (usually -M only considers a file that disappeared -as the source of a rename), and the number `n` controls this aspect of -the -B option (defaults to 50%). `-B20%` specifies that a change with +When used with `-M`, a totally-rewritten file is also considered as the +source of a rename (usually `-M` only considers a file that disappeared +as the source of a rename), and the number _<n>_ controls this aspect of +the `-B` option (defaults to 50%). `-B20%` specifies that a change with addition and deletion compared to 20% or more of the file's size are eligible for being picked up as a possible source of a rename to another file. --M[<n>]:: ---find-renames[=<n>]:: +`-M[<n>]`:: +`--find-renames[=<n>]`:: ifndef::git-log[] Detect renames. endif::git-log[] @@ -580,7 +580,7 @@ ifdef::git-log[] For following files across renames while traversing history, see `--follow`. endif::git-log[] - If `n` is specified, it is a threshold on the similarity + If _<n>_ is specified, it is a threshold on the similarity index (i.e. amount of addition/deletions compared to the file's size). For example, `-M90%` means Git should consider a delete/add pair to be a rename if more than 90% of the file @@ -590,12 +590,12 @@ endif::git-log[] the same as `-M5%`. To limit detection to exact renames, use `-M100%`. The default similarity index is 50%. --C[<n>]:: ---find-copies[=<n>]:: +`-C[<n>]`:: +`--find-copies[=<n>]`:: Detect copies as well as renames. See also `--find-copies-harder`. - If `n` is specified, it has the same meaning as for `-M<n>`. + If _<n>_ is specified, it has the same meaning as for `-M<n>`. ---find-copies-harder:: +`--find-copies-harder`:: For performance reasons, by default, `-C` option finds copies only if the original file of the copy was modified in the same changeset. This flag makes the command @@ -604,8 +604,8 @@ endif::git-log[] projects, so use it with caution. Giving more than one `-C` option has the same effect. --D:: ---irreversible-delete:: +`-D`:: +`--irreversible-delete`:: Omit the preimage for deletes, i.e. print only the header but not the diff between the preimage and `/dev/null`. The resulting patch is not meant to be applied with `patch` or `git apply`; this is @@ -617,7 +617,7 @@ endif::git-log[] When used together with `-B`, omit also the preimage in the deletion part of a delete/create pair. --l<num>:: +`-l<num>`:: The `-M` and `-C` options involve some preliminary steps that can detect subsets of renames/copies cheaply, followed by an exhaustive fallback portion that compares all remaining @@ -627,11 +627,11 @@ of a delete/create pair. destinations, this exhaustive check is O(N^2). This option prevents the exhaustive portion of rename/copy detection from running if the number of source/destination files involved - exceeds the specified number. Defaults to diff.renameLimit. + exceeds the specified number. Defaults to `diff.renameLimit`. Note that a value of 0 is treated as unlimited. ifndef::git-format-patch[] ---diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]:: +`--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]`:: Select only files that are Added (`A`), Copied (`C`), Deleted (`D`), Modified (`M`), Renamed (`R`), have their type (i.e. regular file, symlink, submodule, ...) changed (`T`), @@ -649,9 +649,9 @@ Also, these upper-case letters can be downcased to exclude. E.g. Note that not all diffs can feature all types. For instance, copied and renamed entries cannot appear if detection for those types is disabled. --S<string>:: +`-S<string>`:: Look for differences that change the number of occurrences of - the specified string (i.e. addition/deletion) in a file. + the specified _<string>_ (i.e. addition/deletion) in a file. Intended for the scripter's use. + It is useful when you're looking for an exact block of code (like a @@ -662,11 +662,11 @@ very first version of the block. + Binary files are searched as well. --G<regex>:: +`-G<regex>`:: Look for differences whose patch text contains added/removed - lines that match <regex>. + lines that match _<regex>_. + -To illustrate the difference between `-S<regex> --pickaxe-regex` and +To illustrate the difference between `-S<regex>` `--pickaxe-regex` and `-G<regex>`, consider a commit with the following diff in the same file: + @@ -686,7 +686,7 @@ filter will be ignored. See the 'pickaxe' entry in linkgit:gitdiffcore[7] for more information. ---find-object=<object-id>:: +`--find-object=<object-id>`:: Look for differences that change the number of occurrences of the specified object. Similar to `-S`, just the argument is different in that it doesn't search for a specific string but for a specific @@ -695,25 +695,25 @@ information. The object can be a blob or a submodule commit. It implies the `-t` option in `git-log` to also find trees. ---pickaxe-all:: +`--pickaxe-all`:: When `-S` or `-G` finds a change, show all the changes in that changeset, not just the files that contain the change - in <string>. + in _<string>_. ---pickaxe-regex:: - Treat the <string> given to `-S` as an extended POSIX regular +`--pickaxe-regex`:: + Treat the _<string>_ given to `-S` as an extended POSIX regular expression to match. endif::git-format-patch[] --O<orderfile>:: +`-O<orderfile>`:: Control the order in which files appear in the output. This overrides the `diff.orderFile` configuration variable (see linkgit:git-config[1]). To cancel `diff.orderFile`, use `-O/dev/null`. + The output order is determined by the order of glob patterns in -<orderfile>. +_<orderfile>_. All files with pathnames that match the first pattern are output first, all files with pathnames that match the second pattern (but not the first) are output next, and so on. @@ -724,7 +724,7 @@ If multiple pathnames have the same rank (they match the same pattern but no earlier patterns), their output order relative to each other is the normal order. + -<orderfile> is parsed as follows: +_<orderfile>_ is parsed as follows: + -- - Blank lines are ignored, so they can be used as separators for @@ -738,106 +738,107 @@ the normal order. -- + Patterns have the same syntax and semantics as patterns used for -fnmatch(3) without the FNM_PATHNAME flag, except a pathname also +`fnmatch`(3) without the `FNM_PATHNAME` flag, except a pathname also matches a pattern if removing any number of the final pathname components matches the pattern. For example, the pattern "`foo*bar`" matches "`fooasdfbar`" and "`foo/bar/baz/asdf`" but not "`foobarx`". ---skip-to=<file>:: ---rotate-to=<file>:: - Discard the files before the named <file> from the output +`--skip-to=<file>`:: +`--rotate-to=<file>`:: + Discard the files before the named _<file>_ from the output (i.e. 'skip to'), or move them to the end of the output (i.e. 'rotate to'). These options were invented primarily for the use of the `git difftool` command, and may not be very useful otherwise. ifndef::git-format-patch[] --R:: +`-R`:: Swap two inputs; that is, show differences from index or on-disk file to tree contents. endif::git-format-patch[] ---relative[=<path>]:: ---no-relative:: +`--relative[=<path>]`:: +`--no-relative`:: When run from a subdirectory of the project, it can be told to exclude changes outside the directory and show pathnames relative to it with this option. When you are not in a subdirectory (e.g. in a bare repository), you can name which subdirectory to make the output relative - to by giving a <path> as an argument. + to by giving a _<path>_ as an argument. `--no-relative` can be used to countermand both `diff.relative` config option and previous `--relative`. --a:: ---text:: +`-a`:: +`--text`:: Treat all files as text. ---ignore-cr-at-eol:: +`--ignore-cr-at-eol`:: Ignore carriage-return at the end of line when doing a comparison. ---ignore-space-at-eol:: +`--ignore-space-at-eol`:: Ignore changes in whitespace at EOL. --b:: ---ignore-space-change:: +`-b`:: +`--ignore-space-change`:: Ignore changes in amount of whitespace. This ignores whitespace at line end, and considers all other sequences of one or more whitespace characters to be equivalent. --w:: ---ignore-all-space:: +`-w`:: +`--ignore-all-space`:: Ignore whitespace when comparing lines. This ignores differences even if one line has whitespace where the other line has none. ---ignore-blank-lines:: +`--ignore-blank-lines`:: Ignore changes whose lines are all blank. --I<regex>:: ---ignore-matching-lines=<regex>:: - Ignore changes whose all lines match <regex>. This option may + +`-I<regex>`:: +`--ignore-matching-lines=<regex>`:: + Ignore changes whose all lines match _<regex>_. This option may be specified more than once. ---inter-hunk-context=<lines>:: - Show the context between diff hunks, up to the specified number +`--inter-hunk-context=<number>`:: + Show the context between diff hunks, up to the specified _<number>_ of lines, thereby fusing hunks that are close to each other. Defaults to `diff.interHunkContext` or 0 if the config option is unset. --W:: ---function-context:: +`-W`:: +`--function-context`:: Show whole function as context lines for each change. The function names are determined in the same way as - `git diff` works out patch hunk headers (see 'Defining a - custom hunk-header' in linkgit:gitattributes[5]). + `git diff` works out patch hunk headers (see "Defining a + custom hunk-header" in linkgit:gitattributes[5]). ifndef::git-format-patch[] ifndef::git-log[] ---exit-code:: - Make the program exit with codes similar to diff(1). +`--exit-code`:: + Make the program exit with codes similar to `diff`(1). That is, it exits with 1 if there were differences and 0 means no differences. ---quiet:: +`--quiet`:: Disable all output of the program. Implies `--exit-code`. Disables execution of external diff helpers whose exit code is not trusted, i.e. their respective configuration option - `diff.trustExitCode` or `diff.<driver>.trustExitCode` or + `diff.trustExitCode` or ++diff.++__<driver>__++.trustExitCode++ or environment variable `GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE` is false. endif::git-log[] endif::git-format-patch[] ---ext-diff:: +`--ext-diff`:: Allow an external diff helper to be executed. If you set an external diff driver with linkgit:gitattributes[5], you need to use this option with linkgit:git-log[1] and friends. ---no-ext-diff:: +`--no-ext-diff`:: Disallow external diff drivers. ---textconv:: ---no-textconv:: +`--textconv`:: +`--no-textconv`:: Allow (or disallow) external text conversion filters to be run when comparing binary files. See linkgit:gitattributes[5] for details. Because textconv filters are typically a one-way @@ -847,42 +848,42 @@ endif::git-format-patch[] linkgit:git-log[1], but not for linkgit:git-format-patch[1] or diff plumbing commands. ---ignore-submodules[=<when>]:: - Ignore changes to submodules in the diff generation. <when> can be - either "none", "untracked", "dirty" or "all", which is the default. - Using "none" will consider the submodule modified when it either contains - untracked or modified files or its HEAD differs from the commit recorded + +`--ignore-submodules[=(none|untracked|dirty|all)]`:: + Ignore changes to submodules in the diff generation. `all` is the default. + Using `none` will consider the submodule modified when it either contains + untracked or modified files or its `HEAD` differs from the commit recorded in the superproject and can be used to override any settings of the - 'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When - "untracked" is used submodules are not considered dirty when they only + `ignore` option in linkgit:git-config[1] or linkgit:gitmodules[5]. When + `untracked` is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified - content). Using "dirty" ignores all changes to the work tree of submodules, + content). Using `dirty` ignores all changes to the work tree of submodules, only changes to the commits stored in the superproject are shown (this was - the behavior until 1.7.0). Using "all" hides all changes to submodules. + the behavior until 1.7.0). Using `all` hides all changes to submodules. ---src-prefix=<prefix>:: - Show the given source prefix instead of "a/". +`--src-prefix=<prefix>`:: + Show the given source _<prefix>_ instead of "a/". ---dst-prefix=<prefix>:: - Show the given destination prefix instead of "b/". +`--dst-prefix=<prefix>`:: + Show the given destination _<prefix>_ instead of "b/". ---no-prefix:: +`--no-prefix`:: Do not show any source or destination prefix. ---default-prefix:: +`--default-prefix`:: Use the default source and destination prefixes ("a/" and "b/"). This overrides configuration variables such as `diff.noprefix`, `diff.srcPrefix`, `diff.dstPrefix`, and `diff.mnemonicPrefix` - (see `git-config`(1)). + (see linkgit:git-config[1]). ---line-prefix=<prefix>:: - Prepend an additional prefix to every line of output. +`--line-prefix=<prefix>`:: + Prepend an additional _<prefix>_ to every line of output. ---ita-invisible-in-index:: - By default entries added by "git add -N" appear as an existing - empty file in "git diff" and a new file in "git diff --cached". - This option makes the entry appear as a new file in "git diff" - and non-existent in "git diff --cached". This option could be +`--ita-invisible-in-index`:: + By default entries added by `git add -N` appear as an existing + empty file in `git diff` and a new file in `git diff --cached`. + This option makes the entry appear as a new file in `git diff` + and non-existent in `git diff --cached`. This option could be reverted with `--ita-visible-in-index`. Both options are experimental and could be removed in future. diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index e22b217fba..b01372e4b3 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -1,6 +1,7 @@ --[no-]all:: - Fetch all remotes. This overrides the configuration variable - `fetch.all`. + Fetch all remotes, except for the ones that has the + `remote.<name>.skipFetchAll` configuration variable set. + This overrides the configuration variable fetch.all`. -a:: --append:: @@ -28,7 +29,7 @@ Deepen or shorten the history of a shallow repository to include all reachable commits after <date>. ---shallow-exclude=<revision>:: +--shallow-exclude=<ref>:: Deepen or shorten the history of a shallow repository to exclude commits reachable from a specified remote branch or tag. This option can be specified multiple times. @@ -304,6 +305,9 @@ endif::git-pull[] unknown ones, is server-specific. When multiple `--server-option=<option>` are given, they are all sent to the other side in the order listed on the command line. + When no `--server-option=<option>` is given from the command line, + the values of configuration variable `remote.<name>.serverOption` + are used instead. --show-forced-updates:: By default, git checks if a branch is force-updated during diff --git a/Documentation/fsck-msgids.txt b/Documentation/fsck-msgids.txt index f643585a34..b14bc44ca4 100644 --- a/Documentation/fsck-msgids.txt +++ b/Documentation/fsck-msgids.txt @@ -19,6 +19,18 @@ `badParentSha1`:: (ERROR) A commit object has a bad parent sha1. +`badRefContent`:: + (ERROR) A ref has bad content. + +`badRefFiletype`:: + (ERROR) A ref has a bad file type. + +`badRefName`:: + (ERROR) A ref has an invalid format. + +`badReferentName`:: + (ERROR) The referent name of a symref is invalid. + `badTagName`:: (INFO) A tag has an invalid format. @@ -164,6 +176,35 @@ `nullSha1`:: (WARN) Tree contains entries pointing to a null sha1. +`refMissingNewline`:: + (INFO) A loose ref that does not end with newline(LF). As + valid implementations of Git never created such a loose ref + file, it may become an error in the future. Report to the + git@vger.kernel.org mailing list if you see this error, as + we need to know what tools created such a file. + +`symlinkRef`:: + (INFO) A symbolic link is used as a symref. Report to the + git@vger.kernel.org mailing list if you see this error, as we + are assessing the feasibility of dropping the support to drop + creating symbolic links as symrefs. + +`symrefTargetIsNotARef`:: + (INFO) The target of a symbolic reference points neither to + a root reference nor to a reference starting with "refs/". + Although we allow create a symref pointing to the referent which + is outside the "ref" by using `git symbolic-ref`, we may tighten + the rule in the future. Report to the git@vger.kernel.org + mailing list if you see this error, as we need to know what tools + created such a file. + +`trailingRefContent`:: + (INFO) A loose ref has trailing content. As valid implementations + of Git never created such a loose ref file, it may become an + error in the future. Report to the git@vger.kernel.org mailing + list if you see this error, as we need to know what tools + created such a file. + `treeNotSorted`:: (ERROR) A tree is not properly sorted. diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index aceaa025e3..5f2c3592b8 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -7,12 +7,12 @@ git-add - Add file contents to the index SYNOPSIS -------- -[verse] -'git add' [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] - [--edit | -e] [--[no-]all | -A | --[no-]ignore-removal | [--update | -u]] [--sparse] - [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize] - [--chmod=(+|-)x] [--pathspec-from-file=<file> [--pathspec-file-nul]] - [--] [<pathspec>...] +[synopsis] +git add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] + [--edit | -e] [--[no-]all | -A | --[no-]ignore-removal | [--update | -u]] [--sparse] + [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize] + [--chmod=(+|-)x] [--pathspec-from-file=<file> [--pathspec-file-nul]] + [--] [<pathspec>...] DESCRIPTION ----------- @@ -41,7 +41,7 @@ The `git add` command will not add ignored files by default. If any ignored files were explicitly specified on the command line, `git add` will fail with a list of ignored files. Ignored files reached by directory recursion or filename globbing performed by Git (quote your -globs before the shell) will be silently ignored. The 'git add' command can +globs before the shell) will be silently ignored. The `git add` command can be used to add ignored files with the `-f` (force) option. Please see linkgit:git-commit[1] for alternative ways to add content to a @@ -50,7 +50,7 @@ commit. OPTIONS ------- -<pathspec>...:: +`<pathspec>...`:: Files to add content from. Fileglobs (e.g. `*.c`) can be given to add all matching files. Also a leading directory name (e.g. `dir` to add `dir/file1` @@ -66,35 +66,35 @@ OPTIONS For more details about the _<pathspec>_ syntax, see the 'pathspec' entry in linkgit:gitglossary[7]. --n:: ---dry-run:: +`-n`:: +`--dry-run`:: Don't actually add the file(s), just show if they exist and/or will be ignored. --v:: ---verbose:: +`-v`:: +`--verbose`:: Be verbose. --f:: ---force:: +`-f`:: +`--force`:: Allow adding otherwise ignored files. ---sparse:: +`--sparse`:: Allow updating index entries outside of the sparse-checkout cone. Normally, `git add` refuses to update index entries whose paths do not fit within the sparse-checkout cone, since those files might be removed from the working tree without warning. See linkgit:git-sparse-checkout[1] for more details. --i:: ---interactive:: +`-i`:: +`--interactive`:: Add modified contents in the working tree interactively to the index. Optional path arguments may be supplied to limit operation to a subset of the working tree. See ``Interactive mode'' for details. --p:: ---patch:: +`-p`:: +`--patch`:: Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the @@ -104,8 +104,8 @@ This effectively runs `add --interactive`, but bypasses the initial command menu and directly jumps to the `patch` subcommand. See ``Interactive mode'' for details. --e:: ---edit:: +`-e`:: +`--edit`:: Open the diff vs. the index in an editor and let the user edit it. After the editor was closed, adjust the hunk headers and apply the patch to the index. @@ -116,8 +116,8 @@ quicker and more flexible than using the interactive hunk selector. However, it is easy to confuse oneself and create a patch that does not apply to the index. See EDITING PATCHES below. --u:: ---update:: +`-u`:: +`--update`:: Update the index just where it already has an entry matching _<pathspec>_. This removes as well as modifies index entries to match the working tree, but adds no new files. @@ -127,9 +127,9 @@ tracked files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories). --A:: ---all:: ---no-ignore-removal:: +`-A`:: +`--all`:: +`--no-ignore-removal`:: Update the index not only where the working tree has a file matching _<pathspec>_ but also where the index already has an entry. This adds, modifies, and removes index entries to @@ -140,77 +140,77 @@ files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories). ---no-all:: ---ignore-removal:: +`--no-all`:: +`--ignore-removal`:: Update the index by adding new files that are unknown to the index and files modified in the working tree, but ignore files that have been removed from the working tree. This option is a no-op when no _<pathspec>_ is used. + This option is primarily to help users who are used to older -versions of Git, whose "git add _<pathspec>_..." was a synonym -for "git add --no-all _<pathspec>_...", i.e. ignored removed files. +versions of Git, whose `git add <pathspec>...` was a synonym +for `git add --no-all <pathspec>...`, i.e. ignored removed files. --N:: ---intent-to-add:: +`-N`:: +`--intent-to-add`:: Record only the fact that the path will be added later. An entry for the path is placed in the index with no content. This is useful for, among other things, showing the unstaged content of such files with `git diff` and committing them with `git commit -a`. ---refresh:: +`--refresh`:: Don't add the file(s), but only refresh their stat() information in the index. ---ignore-errors:: +`--ignore-errors`:: If some files could not be added because of errors indexing them, do not abort the operation, but continue adding the others. The command shall still exit with non-zero status. The configuration variable `add.ignoreErrors` can be set to true to make this the default behaviour. ---ignore-missing:: - This option can only be used together with --dry-run. By using +`--ignore-missing`:: + This option can only be used together with `--dry-run`. By using this option the user can check if any of the given files would be ignored, no matter if they are already present in the work tree or not. ---no-warn-embedded-repo:: +`--no-warn-embedded-repo`:: By default, `git add` will warn when adding an embedded repository to the index without using `git submodule add` to create an entry in `.gitmodules`. This option will suppress the warning (e.g., if you are manually performing operations on submodules). ---renormalize:: +`--renormalize`:: Apply the "clean" process freshly to all tracked files to forcibly add them again to the index. This is useful after changing `core.autocrlf` configuration or the `text` attribute - in order to correct files added with wrong CRLF/LF line endings. + in order to correct files added with wrong _CRLF/LF_ line endings. This option implies `-u`. Lone CR characters are untouched, thus - while a CRLF cleans to LF, a CRCRLF sequence is only partially - cleaned to CRLF. + while a _CRLF_ cleans to _LF_, a _CRCRLF_ sequence is only partially + cleaned to _CRLF_. ---chmod=(+|-)x:: +`--chmod=(+|-)x`:: Override the executable bit of the added files. The executable bit is only changed in the index, the files on disk are left unchanged. ---pathspec-from-file=<file>:: +`--pathspec-from-file=<file>`:: Pathspec is passed in _<file>_ instead of commandline args. If _<file>_ is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be + elements are separated by _LF_ or _CR/LF_. Pathspec elements can be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). -\--:: +`--`:: This option can be used to separate command-line options from the list of files, (useful when filenames might be mistaken for command-line options). @@ -219,18 +219,18 @@ for "git add --no-all _<pathspec>_...", i.e. ignored removed files. EXAMPLES -------- -* Adds content from all `*.txt` files under `Documentation` directory +* Adds content from all ++*.txt++ files under `Documentation` directory and its subdirectories: + ------------ $ git add Documentation/\*.txt ------------ + -Note that the asterisk `*` is quoted from the shell in this +Note that the asterisk ++*++ is quoted from the shell in this example; this lets the command include the files from subdirectories of `Documentation/` directory. -* Considers adding content from all git-*.sh scripts: +* Considers adding content from all ++git-*.sh++ scripts: + ------------ $ git add git-*.sh @@ -265,7 +265,7 @@ The main command loop has 6 subcommands (plus help and quit). status:: - This shows the change between HEAD and index (i.e. what will be + This shows the change between `HEAD` and index (i.e. what will be committed if you say `git commit`), and between index and working tree files (i.e. what you could stage further before `git commit` using `git add`) for each path. A sample output @@ -277,12 +277,12 @@ status:: 2: +403/-35 +1/-1 add-interactive.c ------------ + -It shows that foo.png has differences from HEAD (but that is +It shows that `foo.png` has differences from `HEAD` (but that is binary so line count cannot be shown) and there is no difference between indexed copy and the working tree version (if the working tree version were also different, 'binary' would have been shown in place of 'nothing'). The -other file, add-interactive.c, has 403 lines added +other file, `add-interactive.c`, has 403 lines added and 35 lines deleted if you commit what is in the index, but working tree file has further modifications (one addition and one deletion). @@ -360,7 +360,7 @@ variable `interactive.singleKey` to `true`. diff:: This lets you review what will be committed (i.e. between - HEAD and index). + `HEAD` and index). EDITING PATCHES @@ -399,7 +399,7 @@ There are also more complex operations that can be performed. But beware that because the patch is applied only to the index and not the working tree, the working tree will appear to "undo" the change in the index. For example, introducing a new line into the index that is in neither -the HEAD nor the working tree will stage the new line for commit, but +the `HEAD` nor the working tree will stage the new line for commit, but the line will appear to be reverted in the working tree. Avoid using these constructs, or do so with extreme caution. @@ -439,6 +439,7 @@ CONFIGURATION include::includes/cmd-config-section-all.txt[] +:git-add: 1 include::config/add.txt[] SEE ALSO diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 9cce68a38b..dd4a61ef28 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -9,7 +9,8 @@ git-apply - Apply a patch to files and/or to the index SYNOPSIS -------- [verse] -'git apply' [--stat] [--numstat] [--summary] [--check] [--index | --intent-to-add] [--3way] +'git apply' [--stat] [--numstat] [--summary] [--check] + [--index | --intent-to-add] [--3way] [--ours | --theirs | --union] [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse] [--allow-binary-replacement | --binary] [--reject] [-z] [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached] @@ -92,6 +93,12 @@ OPTIONS When used with the `--cached` option, any conflicts are left at higher stages in the cache. +--ours:: +--theirs:: +--union:: + Instead of leaving conflicts in the file, resolve conflicts favouring + our (or their or both) side of the lines. Requires --3way. + --build-fake-ancestor=<file>:: Newer 'git diff' output has embedded 'index information' for each blob to help identify the original version that diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt index 3ab42a19ca..03cd36fe8d 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.txt @@ -23,19 +23,18 @@ the "offline" transfer of Git objects without an active "server" sitting on the other side of the network connection. They can be used to create both incremental and full backups of a -repository, and to relay the state of the references in one repository -to another. +repository (see the "full backup" example in "EXAMPLES"), and to relay +the state of the references in one repository to another (see the second +example). Git commands that fetch or otherwise "read" via protocols such as `ssh://` and `https://` can also operate on bundle files. It is possible linkgit:git-clone[1] a new repository from a bundle, to use linkgit:git-fetch[1] to fetch from one, and to list the references contained within it with linkgit:git-ls-remote[1]. There's no -corresponding "write" support, i.e.a 'git push' into a bundle is not +corresponding "write" support, i.e. a 'git push' into a bundle is not supported. -See the "EXAMPLES" section below for examples of how to use bundles. - BUNDLE FORMAT ------------- @@ -132,7 +131,7 @@ SPECIFYING REFERENCES --------------------- Revisions must be accompanied by reference names to be packaged in a -bundle. +bundle. Alternatively `--all` can be used to package all refs. More than one reference may be packaged, and more than one set of prerequisite objects can be specified. The objects packaged are those not contained in the @@ -203,8 +202,6 @@ It is okay to err on the side of caution, causing the bundle file to contain objects already in the destination, as these are ignored when unpacking at the destination. -If you want to match `git clone --mirror`, which would include your -refs such as `refs/remotes/*`, use `--all`. If you want to provide the same set of refs that a clone directly from the source repository would get, use `--branches --tags` for the `<git-rev-list-args>`. @@ -216,8 +213,34 @@ bundle. EXAMPLES -------- -Assume you want to transfer the history from a repository R1 on machine A -to another repository R2 on machine B. +We'll discuss two cases: + +1. Taking a full backup of a repository +2. Transferring the history of a repository to another machine when the + two machines have no direct connection + +First let's consider a full backup of the repository. The following +command will take a full backup of the repository in the sense that all +refs are included in the bundle: + +---------------- +$ git bundle create backup.bundle --all +---------------- + +But note again that this is only for the refs, i.e. you will only +include refs and commits reachable from those refs. You will not +include other local state, such as the contents of the index, working +tree, the stash, per-repository configuration, hooks, etc. + +You can later recover that repository by using for example +linkgit:git-clone[1]: + +---------------- +$ git clone backup.bundle <new directory> +---------------- + +For the next example, assume you want to transfer the history from a +repository R1 on machine A to another repository R2 on machine B. For whatever reason, direct connection between A and B is not allowed, but we can move data from A to B via some mechanism (CD, email, etc.). We want to update R2 with development made on the branch master in R1. @@ -321,6 +344,24 @@ You can also see what references it offers: $ git ls-remote mybundle ---------------- +DISCUSSION +---------- + +A naive way to make a full backup of a repository is to use something to +the effect of `cp -r <repo> <destination>`. This is discouraged since +the repository could be written to during the copy operation. In turn +some files at `<destination>` could be corrupted. + +This is why it is recommended to use Git tooling for making repository +backups, either with this command or with e.g. linkgit:git-clone[1]. +But keep in mind that these tools will not help you backup state other +than refs and commits. In other words they will not help you backup +contents of the index, working tree, the stash, per-repository +configuration, hooks, etc. + +See also linkgit:gitfaq[7], section "TRANSFERS" for a discussion of the +problems associated with file syncing across systems. + FILE FORMAT ----------- diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index bd95a6c10a..d5890ae368 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -270,9 +270,9 @@ BATCH OUTPUT ------------ If `--batch` or `--batch-check` is given, `cat-file` will read objects -from stdin, one per line, and print information about them. By default, -the whole line is considered as an object, as if it were fed to -linkgit:git-rev-parse[1]. +from stdin, one per line, and print information about them in the same +order as they have been read. By default, the whole line is +considered as an object, as if it were fed to linkgit:git-rev-parse[1]. When `--batch-command` is given, `cat-file` will read commands from stdin, one per line, and print information based on the command given. With diff --git a/Documentation/git-check-mailmap.txt b/Documentation/git-check-mailmap.txt index 02f4418323..966c91c46a 100644 --- a/Documentation/git-check-mailmap.txt +++ b/Documentation/git-check-mailmap.txt @@ -15,10 +15,10 @@ SYNOPSIS DESCRIPTION ----------- -For each ``Name $$<user@host>$$'' or ``$$<user@host>$$'' from the command-line -or standard input (when using `--stdin`), look up the person's canonical name -and email address (see "Mapping Authors" below). If found, print them; -otherwise print the input as-is. +For each ``Name $$<user@host>$$'', ``$$<user@host>$$'', or ``$$user@host$$'' +from the command-line or standard input (when using `--stdin`), look up the +person's canonical name and email address (see "Mapping Authors" below). If +found, print them; otherwise print the input as-is. OPTIONS @@ -27,6 +27,16 @@ OPTIONS Read contacts, one per line, from the standard input after exhausting contacts provided on the command-line. +--mailmap-file=<file>:: + In addition to any configured mailmap files, read the specified + mailmap file. Entries in this file take precedence over entries in + either the default mailmap file or any configured mailmap file. + +--mailmap-blob=<blob>:: + Like `--mailmap-file`, but consider the value as a reference to a + blob in the repository. If both `--mailmap-file` and + `--mailmap-blob` are specified, entries in `--mailmap-file` will + take precedence. OUTPUT ------ diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 8bdfa54ab0..bf26655764 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -290,10 +290,10 @@ Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. --ignore-other-worktrees:: - `git checkout` refuses when the wanted ref is already checked - out by another worktree. This option makes it check the ref - out anyway. In other words, the ref can be held by more than one - worktree. + `git checkout` refuses when the wanted branch is already checked + out or otherwise in use by another worktree. This option makes + it check the branch out anyway. In other words, the branch can + be in use by more than one worktree. --overwrite-ignore:: --no-overwrite-ignore:: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 8e925db7e9..de8d8f5893 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -8,16 +8,16 @@ git-clone - Clone a repository into a new directory SYNOPSIS -------- -[verse] -`git clone` [++--template=++__<template-directory>__] - [`-l`] [`-s`] [`--no-hardlinks`] [`-q`] [`-n`] [`--bare`] [`--mirror`] - [`-o` _<name>_] [`-b` _<name>_] [`-u` _<upload-pack>_] [`--reference` _<repository>_] - [`--dissociate`] [`--separate-git-dir` _<git-dir>_] - [`--depth` _<depth>_] [`--`[`no-`]{empty}`single-branch`] [`--no-tags`] - [++--recurse-submodules++[++=++__<pathspec>__]] [++--++[++no-++]{empty}++shallow-submodules++] - [`--`[`no-`]{empty}`remote-submodules`] [`--jobs` _<n>_] [`--sparse`] [`--`[`no-`]{empty}`reject-shallow`] - [++--filter=++__<filter-spec>__] [`--also-filter-submodules`]] [`--`] _<repository>_ - [_<directory>_] +[synopsis] +git clone [--template=<template-directory>] + [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] + [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] + [--dissociate] [--separate-git-dir <git-dir>] + [--depth <depth>] [--[no-]single-branch] [--no-tags] + [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules] + [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow] + [--filter=<filter-spec>] [--also-filter-submodules]] [--] <repository> + [<directory>] DESCRIPTION ----------- @@ -52,7 +52,7 @@ OPTIONS to save space when possible. + If the repository is specified as a local path (e.g., `/path/to/repo`), -this is the default, and --local is essentially a no-op. If the +this is the default, and `--local` is essentially a no-op. If the repository is specified as a URL, then this flag is ignored (and we never use the local optimizations). Specifying `--no-local` will override the default when `/path/to/repo` is given, using the regular @@ -63,9 +63,12 @@ symbolic link, the clone will fail. This is a security measure to prevent the unintentional copying of files by dereferencing the symbolic links. + +This option does not work with repositories owned by other users for security +reasons, and `--no-local` must be specified for the clone to succeed. ++ *NOTE*: this operation can race with concurrent modification to the -source repository, similar to running `cp -r src dst` while modifying -`src`. +source repository, similar to running `cp -r <src> <dst>` while modifying +_<src>_. `--no-hardlinks`:: Force the cloning process from a repository on a local @@ -101,7 +104,7 @@ If you want to break the dependency of a repository cloned with `--shared` on its source repository, you can simply run `git repack -a` to copy all objects from the source repository into a pack in the cloned repository. -`--reference`[`-if-able`] _<repository>_:: +`--reference[-if-able] <repository>`:: If the reference _<repository>_ is on the local machine, automatically setup `.git/objects/info/alternates` to obtain objects from the reference _<repository>_. Using @@ -142,17 +145,20 @@ objects from the source repository into a pack in the cloned repository. is specified. This flag forces progress status even if the standard error stream is not directed to a terminal. -++--server-option=++__<option>__:: +`--server-option=<option>`:: Transmit the given string to the server when communicating using protocol version 2. The given string must not contain a NUL or LF character. The server's handling of server options, including unknown ones, is server-specific. - When multiple ++--server-option=++__<option>__ are given, they are all + When multiple `--server-option=<option>` are given, they are all sent to the other side in the order listed on the command line. + When no ++--server-option=++__<option>__ is given from the command + line, the values of configuration variable `remote.<name>.serverOption` + are used instead. `-n`:: `--no-checkout`:: - No checkout of HEAD is performed after the clone is complete. + No checkout of `HEAD` is performed after the clone is complete. `--`[`no-`]`reject-shallow`:: Fail if the source repository is a shallow repository. @@ -162,7 +168,7 @@ objects from the source repository into a pack in the cloned repository. `--bare`:: Make a 'bare' Git repository. That is, instead of creating _<directory>_ and placing the administrative - files in _<directory>_`/.git`, make the _<directory>_ + files in `<directory>/.git`, make the _<directory>_ itself the `$GIT_DIR`. This obviously implies the `--no-checkout` because there is nowhere to check out the working tree. Also the branch heads at the remote are copied directly @@ -177,13 +183,13 @@ objects from the source repository into a pack in the cloned repository. linkgit:git-sparse-checkout[1] command can be used to grow the working directory as needed. -++--filter=++__<filter-spec>__:: +`--filter=<filter-spec>`:: Use the partial clone feature and request that the server sends a subset of reachable objects according to a given object filter. When using `--filter`, the supplied _<filter-spec>_ is used for the partial clone filter. For example, `--filter=blob:none` will filter out all blobs (file contents) until needed by Git. Also, - ++--filter=blob:limit=++__<size>__ will filter out all blobs of size + `--filter=blob:limit=<size>` will filter out all blobs of size at least _<size>_. For more details on filter specifications, see the `--filter` option in linkgit:git-rev-list[1]. @@ -208,11 +214,11 @@ objects from the source repository into a pack in the cloned repository. `-b` _<name>_:: `--branch` _<name>_:: - Instead of pointing the newly created HEAD to the branch pointed - to by the cloned repository's HEAD, point to _<name>_ branch + Instead of pointing the newly created `HEAD` to the branch pointed + to by the cloned repository's `HEAD`, point to _<name>_ branch instead. In a non-bare repository, this is the branch that will be checked out. - `--branch` can also take tags and detaches the HEAD at that commit + `--branch` can also take tags and detaches the `HEAD` at that commit in the resulting repository. `-u` _<upload-pack>_:: @@ -221,12 +227,12 @@ objects from the source repository into a pack in the cloned repository. via ssh, this specifies a non-default path for the command run on the other end. -++--template=++__<template-directory>__:: +`--template=<template-directory>`:: Specify the directory from which templates will be used; (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].) -`-c` __<key>__++=++__<value>__:: -`--config` __<key>__++=++__<value>__:: +`-c` `<key>=<value>`:: +`--config` `<key>=<value>`:: Set a configuration variable in the newly-created repository; this takes effect immediately after the repository is initialized, but before the remote history is fetched or any @@ -239,25 +245,25 @@ objects from the source repository into a pack in the cloned repository. Due to limitations of the current implementation, some configuration variables do not take effect until after the initial fetch and checkout. Configuration variables known to not take effect are: -++remote.++__<name>__++.mirror++ and ++remote.++__<name>__++.tagOpt++. Use the +`remote.<name>.mirror` and `remote.<name>.tagOpt`. Use the corresponding `--mirror` and `--no-tags` options instead. -`--depth` _<depth>_:: +`--depth <depth>`:: Create a 'shallow' clone with a history truncated to the specified number of commits. Implies `--single-branch` unless `--no-single-branch` is given to fetch the histories near the tips of all branches. If you want to clone submodules shallowly, also pass `--shallow-submodules`. -++--shallow-since=++__<date>__:: +`--shallow-since=<date>`:: Create a shallow clone with a history after the specified time. -++--shallow-exclude=++__<revision>__:: +`--shallow-exclude=<ref>`:: Create a shallow clone with a history, excluding commits reachable from a specified remote branch or tag. This option can be specified multiple times. -`--`[`no-`]`single-branch`:: +`--[no-]single-branch`:: Clone only the history leading to the tip of a single branch, either specified by the `--branch` option or the primary branch remote's `HEAD` points at. @@ -279,13 +285,13 @@ maintain a branch with no references other than a single cloned branch. This is useful e.g. to maintain minimal clones of the default branch of some repository for search indexing. -`--recurse-submodules`[`=`{empty}__<pathspec>__]:: +`--recurse-submodules[=<pathspec>]`:: After the clone is created, initialize and clone submodules - within based on the provided _<pathspec>_. If no _=<pathspec>_ is + within based on the provided _<pathspec>_. If no `=<pathspec>` is provided, all submodules are initialized and cloned. This option can be given multiple times for pathspecs consisting of multiple entries. The resulting clone has `submodule.active` set to - the provided pathspec, or "." (meaning all submodules) if no + the provided pathspec, or "`.`" (meaning all submodules) if no pathspec is provided. + Submodules are initialized and cloned using their default settings. This is @@ -295,23 +301,23 @@ the clone is finished. This option is ignored if the cloned repository does not have a worktree/checkout (i.e. if any of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given) -`--`[`no-`]`shallow-submodules`:: +`--[no-]shallow-submodules`:: All submodules which are cloned will be shallow with a depth of 1. -`--`[`no-`]`remote-submodules`:: +`--[no-]remote-submodules`:: All submodules which are cloned will use the status of the submodule's remote-tracking branch to update the submodule, rather than the superproject's recorded SHA-1. Equivalent to passing `--remote` to `git submodule update`. -`--separate-git-dir=`{empty}__<git-dir>__:: +`--separate-git-dir=<git-dir>`:: Instead of placing the cloned repository where it is supposed to be, place the cloned repository at the specified directory, then make a filesystem-agnostic Git symbolic link to there. The result is Git repository can be separated from working tree. -`--ref-format=`{empty}__<ref-format>__:: +`--ref-format=<ref-format>`:: Specify the given ref storage format for the repository. The valid values are: + @@ -334,7 +340,7 @@ _<directory>_:: for `host.xz:foo/.git`). Cloning into an existing directory is only allowed if the directory is empty. -`--bundle-uri=`{empty}__<uri>__:: +`--bundle-uri=<uri>`:: Before fetching from the remote, fetch a bundle from the given _<uri>_ and unbundle the data into the local repository. The refs in the bundle will be stored under the hidden `refs/bundle/*` @@ -381,6 +387,12 @@ $ cd my-linux $ git clone --bare -l /home/proj/.git /pub/scm/proj.git ------------ +* Clone a local repository from a different user: ++ +------------ +$ git clone --no-local /home/otheruser/proj.git /pub/scm/proj.git +------------ + CONFIGURATION ------------- diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 89ecfc63a8..c822113c11 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git commit' [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend] - [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>)] + [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>] [-F <file> | -m <msg>] [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=<author>] [--date=<date>] [--cleanup=<mode>] [--[no-]status] diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 65c645d461..3e420177c1 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -10,9 +10,9 @@ SYNOPSIS -------- [verse] 'git config list' [<file-option>] [<display-option>] [--includes] -'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name> +'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name> 'git config set' [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value> -'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value> +'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> 'git config rename-section' [<file-option>] <old-name> <new-name> 'git config remove-section' [<file-option>] <name> 'git config edit' [<file-option>] @@ -130,7 +130,7 @@ OPTIONS --all:: With `get`, return all values for a multi-valued key. ----regexp:: +--regexp:: With `get`, interpret the name as a regular expression. Regular expression matching is currently case-sensitive and done against a canonicalized version of the key in which section and variable names @@ -309,7 +309,7 @@ recommended to migrate to the new syntax. Replaced by `git config get [--value=<pattern>] <name>`. --get-all <name> [<value-pattern>]:: - Replaced by `git config get [--value=<pattern>] --all --show-names <name>`. + Replaced by `git config get [--value=<pattern>] --all <name>`. --get-regexp <name-regexp>:: Replaced by `git config get --all --show-names --regexp <name-regexp>`. diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index 143318c411..09286a85eb 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -88,7 +88,7 @@ include::pretty-options.txt[] --no-commit-id:: 'git diff-tree' outputs a line with the commit ID when - applicable. This flag suppressed the commit ID output. + applicable. This flag suppresses the commit ID output. -c:: This flag changes the way a merge commit is displayed diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index c065f023ec..e19f31e8b9 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -8,13 +8,13 @@ git-diff - Show changes between commits, commit and working tree, etc SYNOPSIS -------- -[verse] -'git diff' [<options>] [<commit>] [--] [<path>...] -'git diff' [<options>] --cached [--merge-base] [<commit>] [--] [<path>...] -'git diff' [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...] -'git diff' [<options>] <commit>...<commit> [--] [<path>...] -'git diff' [<options>] <blob> <blob> -'git diff' [<options>] --no-index [--] <path> <path> +[synopsis] +git diff [<options>] [<commit>] [--] [<path>...] +git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...] +git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...] +git diff [<options>] <commit>...<commit> [--] [<path>...] +git diff [<options>] <blob> <blob> +git diff [<options>] --no-index [--] <path> <path> DESCRIPTION ----------- @@ -23,7 +23,7 @@ between the index and a tree, changes between two trees, changes resulting from a merge, changes between two blob objects, or changes between two files on disk. -'git diff' [<options>] [--] [<path>...]:: +`git diff [<options>] [--] [<path>...]`:: This form is to view the changes you made relative to the index (staging area for the next commit). In other @@ -31,7 +31,7 @@ files on disk. further add to the index but you still haven't. You can stage these changes by using linkgit:git-add[1]. -'git diff' [<options>] --no-index [--] <path> <path>:: +`git diff [<options>] --no-index [--] <path> <path>`:: This form is to compare the given two paths on the filesystem. You can omit the `--no-index` option when @@ -40,82 +40,82 @@ files on disk. or when running the command outside a working tree controlled by Git. This form implies `--exit-code`. -'git diff' [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]:: +`git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]`:: This form is to view the changes you staged for the next - commit relative to the named <commit>. Typically you + commit relative to the named _<commit>_. Typically you would want comparison with the latest commit, so if you - do not give <commit>, it defaults to HEAD. - If HEAD does not exist (e.g. unborn branches) and - <commit> is not given, it shows all staged changes. - --staged is a synonym of --cached. + do not give _<commit>_, it defaults to `HEAD`. + If `HEAD` does not exist (e.g. unborn branches) and + _<commit>_ is not given, it shows all staged changes. + `--staged` is a synonym of `--cached`. + -If --merge-base is given, instead of using <commit>, use the merge base -of <commit> and HEAD. `git diff --cached --merge-base A` is equivalent to +If `--merge-base` is given, instead of using _<commit>_, use the merge base +of _<commit>_ and `HEAD`. `git diff --cached --merge-base A` is equivalent to `git diff --cached $(git merge-base A HEAD)`. -'git diff' [<options>] [--merge-base] <commit> [--] [<path>...]:: +`git diff [<options>] [--merge-base] <commit> [--] [<path>...]`:: This form is to view the changes you have in your - working tree relative to the named <commit>. You can - use HEAD to compare it with the latest commit, or a + working tree relative to the named _<commit>_. You can + use `HEAD` to compare it with the latest commit, or a branch name to compare with the tip of a different branch. + -If --merge-base is given, instead of using <commit>, use the merge base -of <commit> and HEAD. `git diff --merge-base A` is equivalent to +If `--merge-base` is given, instead of using _<commit>_, use the merge base +of _<commit>_ and `HEAD`. `git diff --merge-base A` is equivalent to `git diff $(git merge-base A HEAD)`. -'git diff' [<options>] [--merge-base] <commit> <commit> [--] [<path>...]:: +`git diff [<options>] [--merge-base] <commit> <commit> [--] [<path>...]`:: This is to view the changes between two arbitrary - <commit>. + _<commit>_. + -If --merge-base is given, use the merge base of the two commits for the +If `--merge-base` is given, use the merge base of the two commits for the "before" side. `git diff --merge-base A B` is equivalent to `git diff $(git merge-base A B) B`. -'git diff' [<options>] <commit> <commit>... <commit> [--] [<path>...]:: +`git diff [<options>] <commit> <commit>...<commit> [--] [<path>...]`:: This form is to view the results of a merge commit. The first - listed <commit> must be the merge itself; the remaining two or + listed _<commit>_ must be the merge itself; the remaining two or more commits should be its parents. Convenient ways to produce - the desired set of revisions are to use the suffixes `^@` and - `^!`. If A is a merge commit, then `git diff A A^@`, + the desired set of revisions are to use the suffixes `@` and + `^!`. If `A` is a merge commit, then `git diff A A^@`, `git diff A^!` and `git show A` all give the same combined diff. -'git diff' [<options>] <commit>..<commit> [--] [<path>...]:: +`git diff [<options>] <commit>..<commit> [--] [<path>...]`:: This is synonymous to the earlier form (without the `..`) for - viewing the changes between two arbitrary <commit>. If <commit> on + viewing the changes between two arbitrary _<commit>_. If _<commit>_ on one side is omitted, it will have the same effect as - using HEAD instead. + using `HEAD` instead. -'git diff' [<options>] <commit>\...<commit> [--] [<path>...]:: +`git diff [<options>] <commit>...<commit> [--] [<path>...]`:: This form is to view the changes on the branch containing - and up to the second <commit>, starting at a common ancestor - of both <commit>. `git diff A...B` is equivalent to + and up to the second _<commit>_, starting at a common ancestor + of both _<commit>_. `git diff A...B` is equivalent to `git diff $(git merge-base A B) B`. You can omit any one - of <commit>, which has the same effect as using HEAD instead. + of _<commit>_, which has the same effect as using `HEAD` instead. Just in case you are doing something exotic, it should be -noted that all of the <commit> in the above description, except +noted that all of the _<commit>_ in the above description, except in the `--merge-base` case and in the last two forms that use `..` -notations, can be any <tree>. A tree of interest is the one pointed to -by the ref named `AUTO_MERGE`, which is written by the 'ort' merge +notations, can be any _<tree>_. A tree of interest is the one pointed to +by the ref named `AUTO_MERGE`, which is written by the `ort` merge strategy upon hitting merge conflicts (see linkgit:git-merge[1]). Comparing the working tree with `AUTO_MERGE` shows changes you've made so far to resolve textual conflicts (see the examples below). -For a more complete list of ways to spell <commit>, see +For a more complete list of ways to spell _<commit>_, see "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7]. -However, "diff" is about comparing two _endpoints_, not ranges, -and the range notations (`<commit>..<commit>` and -`<commit>...<commit>`) do not mean a range as defined in the +However, `diff` is about comparing two _endpoints_, not ranges, +and the range notations (`<commit>..<commit>` and `<commit>...<commit>`) +do not mean a range as defined in the "SPECIFYING RANGES" section in linkgit:gitrevisions[7]. -'git diff' [<options>] <blob> <blob>:: +`git diff [<options>] <blob> <blob>`:: This form is to view the differences between the raw contents of two blob objects. @@ -125,22 +125,31 @@ OPTIONS :git-diff: 1 include::diff-options.txt[] --1 --base:: --2 --ours:: --3 --theirs:: - Compare the working tree with the "base" version (stage #1), - "our branch" (stage #2) or "their branch" (stage #3). The - index contains these stages only for unmerged entries i.e. - while resolving conflicts. See linkgit:git-read-tree[1] - section "3-Way Merge" for detailed information. +`-1`:: +`--base`:: +`-2`:: +`--ours`:: +`-3`:: +`--theirs`:: + Compare the working tree with ++ +-- + * the "base" version (stage #1) when using `-1` or `--base`, + * "our branch" (stage #2) when using `-2` or `--ours`, or + * "their branch" (stage #3) when using `-3` or `--theirs`. +-- ++ +The index contains these stages only for unmerged entries i.e. +while resolving conflicts. See linkgit:git-read-tree[1] +section "3-Way Merge" for detailed information. --0:: +`-0`:: Omit diff output for unmerged entries and just show "Unmerged". Can be used only when comparing the working tree with the index. -<path>...:: - The <paths> parameters, when given, are used to limit +`<path>...`:: + The _<path>_ parameters, when given, are used to limit the diff to the named paths (you can give directory names and get diff for all files under them). @@ -225,11 +234,12 @@ CONFIGURATION include::includes/cmd-config-section-all.txt[] +:git-diff: 1 include::config/diff.txt[] SEE ALSO -------- -diff(1), +`diff`(1), linkgit:git-difftool[1], linkgit:git-log[1], linkgit:gitdiffcore[7], diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index b3467664d3..b5223576a7 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -91,7 +91,7 @@ be in a separate packet, and the list must end with a flush packet. Deepen or shorten the history of a shallow repository to include all reachable commits after <date>. ---shallow-exclude=<revision>:: +--shallow-exclude=<ref>:: Deepen or shorten the history of a shallow repository to exclude commits reachable from a specified remote branch or tag. This option can be specified multiple times. diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index c1dd12b93c..d3764401a2 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -264,6 +264,48 @@ ahead-behind:<committish>:: commits ahead and behind, respectively, when comparing the output ref to the `<committish>` specified in the format. +is-base:<committish>:: + In at most one row, `(<committish>)` will appear to indicate the ref + that is most likely the ref used as a starting point for the branch + that produced `<committish>`. This choice is made using a heuristic: + choose the ref that minimizes the number of commits in the + first-parent history of `<committish>` and not in the first-parent + history of the ref. ++ +For example, consider the following figure of first-parent histories of +several refs: ++ +---- +*--*--*--*--*--* refs/heads/A +\ + \ + *--*--*--* refs/heads/B + \ \ + \ \ + * * refs/heads/C + \ + \ + *--* refs/heads/D +---- ++ +Here, if `A`, `B`, and `C` are the filtered references, and the format +string is `%(refname):%(is-base:D)`, then the output would be ++ +---- +refs/heads/A: +refs/heads/B:(D) +refs/heads/C: +---- ++ +This is because the first-parent history of `D` has its earliest +intersection with the first-parent histories of the filtered refs at a +common first-parent ancestor of `B` and `C` and ties are broken by the +earliest ref in the sorted order. ++ +Note that this token will not appear if the first-parent history of +`<committish>` does not intersect the first-parent histories of the +filtered refs. + describe[:options]:: A human-readable name, like linkgit:git-describe[1]; empty string for undescribable commits. The `describe` string may diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 8708b31593..5dc7bb4cfc 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -250,7 +250,7 @@ is not complete yet ("WIP" stands for "Work In Progress"). + If the convention of the receiving community for a particular extra string is to have it _after_ the subject prefix, the string _<rfc>_ -can be prefixed with a dash ("`-`") to signal that the the rest of +can be prefixed with a dash ("`-`") to signal that the rest of the _<rfc>_ string should be appended to the subject prefix instead, e.g., `--rfc='-(WIP)'` results in "PATCH (WIP)". diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index b5561c458a..370e22faae 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -9,7 +9,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository SYNOPSIS -------- [verse] -'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune] [--force] [--keep-largest-pack] +'git gc' [--aggressive] [--auto] [--[no-]detach] [--quiet] [--prune=<date> | --no-prune] [--force] [--keep-largest-pack] DESCRIPTION ----------- @@ -53,6 +53,9 @@ configuration options such as `gc.auto` and `gc.autoPackLimit`, all other housekeeping tasks (e.g. rerere, working trees, reflog...) will be performed as well. +--[no-]detach:: + Run in the background if the system supports it. This option overrides + the `gc.autoDetach` config. --[no-]cruft:: When expiring unreachable objects, pack them separately into a diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt index 5a20deefd5..58dd5b5f0e 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.txt @@ -139,6 +139,13 @@ include::object-format-disclaimer.txt[] written. If a `<message>` is provided, then that content will be written to the .promisor file for future reference. See link:technical/partial-clone.html[partial clone] for more information. ++ +Also, if there are objects in the given pack that references non-promisor +objects (in the repo), repacks those non-promisor objects into a promisor +pack. This avoids a situation in which a repo has non-promisor objects that are +accessible through promisor objects. ++ +Requires <pack-file> to not be specified. NOTES ----- diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index daff93bd16..315f7f7530 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -8,12 +8,12 @@ git-init - Create an empty Git repository or reinitialize an existing one SYNOPSIS -------- -[verse] -`git init` [`-q` | `--quiet`] [`--bare`] [++--template=++__<template-directory>__] - [`--separate-git-dir` _<git-dir>_] [++--object-format=++__<format>__] - [++--ref-format=++__<format>__] - [`-b` _<branch-name>_ | ++--initial-branch=++__<branch-name>__] - [++--shared++[++=++__<permissions>__]] [_<directory>_] +[synopsis] +git init [-q | --quiet] [--bare] [--template=<template-directory>] + [--separate-git-dir <git-dir>] [--object-format=<format>] + [--ref-format=<format>] + [-b <branch-name> | --initial-branch=<branch-name>] + [--shared[=<permissions>]] [<directory>] DESCRIPTION @@ -25,11 +25,11 @@ directory with subdirectories for `objects`, `refs/heads`, commits will be created (see the `--initial-branch` option below for its name). -If the `$GIT_DIR` environment variable is set then it specifies a path +If the `GIT_DIR` environment variable is set then it specifies a path to use instead of `./.git` for the base of the repository. If the object storage directory is specified via the -`$GIT_OBJECT_DIRECTORY` environment variable then the sha1 directories +`GIT_OBJECT_DIRECTORY` environment variable then the sha1 directories are created underneath; otherwise, the default `$GIT_DIR/objects` directory is used. @@ -51,26 +51,22 @@ Only print error and warning messages; all other output will be suppressed. Create a bare repository. If `GIT_DIR` environment is not set, it is set to the current working directory. -++--object-format=++__<format>__:: - +`--object-format=<format>`:: Specify the given object _<format>_ (hash algorithm) for the repository. The valid values are `sha1` and (if enabled) `sha256`. `sha1` is the default. + include::object-format-disclaimer.txt[] -++--ref-format=++__<format>__:: - +`--ref-format=<format>`:: Specify the given ref storage _<format>_ for the repository. The valid values are: + include::ref-storage-format.txt[] -++--template=++__<template-directory>__:: - +`--template=<template-directory>`:: Specify the directory from which templates will be used. (See the "TEMPLATE DIRECTORY" section below.) -++--separate-git-dir=++__<git-dir>__:: - +`--separate-git-dir=<git-dir>`:: Instead of initializing the repository as a directory to either `$GIT_DIR` or `./.git/`, create a text file there containing the path to the actual repository. This file acts as a filesystem-agnostic Git symbolic link to the @@ -78,15 +74,14 @@ repository. + If this is a reinitialization, the repository will be moved to the specified path. -`-b` _<branch-name>_:: -++--initial-branch=++__<branch-name>__:: - +`-b <branch-name>`:: +`--initial-branch=<branch-name>`:: Use _<branch-name>_ for the initial branch in the newly created repository. If not specified, fall back to the default name (currently `master`, but this is subject to change in the future; the name can be customized via the `init.defaultBranch` configuration variable). -++--shared++[++=++(`false`|`true`|`umask`|`group`|`all`|`world`|`everybody`|_<perm>_)]:: +`--shared[=(false|true|umask|group|all|world|everybody|<perm>)]`:: Specify that the Git repository is to be shared amongst several users. This allows users belonging to the same group to push into that diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index d08c7da8f4..58c529afbe 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -219,9 +219,9 @@ followed by the ("attr/<eolattr>"). --format=<format>:: A string that interpolates `%(fieldname)` from the result being shown. - It also interpolates `%%` to `%`, and `%xx` where `xx` are hex digits - interpolates to character with hex code `xx`; for example `%00` - interpolates to `\0` (NUL), `%09` to `\t` (TAB) and %0a to `\n` (LF). + It also interpolates `%%` to `%`, and `%xXX` where `XX` are hex digits + interpolates to character with hex code `XX`; for example `%x00` + interpolates to `\0` (NUL), `%x09` to `\t` (TAB) and %x0a to `\n` (LF). --format cannot be combined with `-s`, `-o`, `-k`, `-t`, `--resolve-undo` and `--eol`. \--:: diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt index 76c86c3ce4..d71c4ab3e2 100644 --- a/Documentation/git-ls-remote.txt +++ b/Documentation/git-ls-remote.txt @@ -81,6 +81,9 @@ OPTIONS character. When multiple `--server-option=<option>` are given, they are all sent to the other side in the order listed on the command line. + When no `--server-option=<option>` is given from the command line, + the values of configuration variable `remote.<name>.serverOption` + are used instead. <repository>:: The "remote" repository to query. This parameter can be diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt index 51d0f7e94b..6e6651309d 100644 --- a/Documentation/git-maintenance.txt +++ b/Documentation/git-maintenance.txt @@ -107,6 +107,9 @@ with the prefetch task, the objects necessary to complete a later real fetch would already be obtained, making the real fetch faster. In the ideal case, it will just become an update to a bunch of remote-tracking branches without any object transfer. ++ +The `remote.<name>.skipFetchAll` configuration can be used to +exclude a particular remote from getting prefetched. gc:: Clean up unnecessary files and optimize the local repository. "GC" @@ -217,7 +220,9 @@ on an hourly basis. Each run executes the "hourly" tasks. At midnight, that process also executes the "daily" tasks. At midnight on the first day of the week, that process also executes the "weekly" tasks. A single process iterates over each registered repository, performing the scheduled -tasks for that frequency. Depending on the number of registered +tasks for that frequency. The processes are scheduled to a random minute of +the hour per client to spread out the load that multiple clients might +generate (e.g. from prefetching). Depending on the number of registered repositories and their sizes, this process may take longer than an hour. In this case, multiple `git maintenance run` commands may run on the same repository at the same time, colliding on the object database lock. This diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 84cb2edf6d..0b6a8a19b1 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -211,9 +211,15 @@ linkgit:git-commit-tree[1], linkgit:git-write-tree[1], linkgit:git-update-ref[1], and linkgit:git-mktag[1]. Thus, it can be used as a part of a series of steps such as: - NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) - test $? -eq 0 || die "There were conflicts..." - NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2) + vi message.txt + BRANCH1=refs/heads/test + BRANCH2=main + NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) || { + echo "There were conflicts..." 1>&2 + exit 1 + } + NEWCOMMIT=$(git commit-tree $NEWTREE -F message.txt \ + -p $BRANCH1 -p $BRANCH2) git update-ref $BRANCH1 $NEWCOMMIT Note that when the exit status is non-zero, `NEWTREE` in this sequence diff --git a/Documentation/git-multi-pack-index.txt b/Documentation/git-multi-pack-index.txt index 3696506eb3..631d5c7d15 100644 --- a/Documentation/git-multi-pack-index.txt +++ b/Documentation/git-multi-pack-index.txt @@ -64,6 +64,12 @@ The file given at `<path>` is expected to be readable, and can contain duplicates. (If a given OID is given more than once, it is marked as preferred if at least one instance of it begins with the special `+` marker). + + --incremental:: + Write an incremental MIDX file containing only objects + and packs not present in an existing MIDX layer. + Migrates non-incremental MIDXs to incremental ones when + necessary. Incompatible with `--bitmap`. -- verify:: @@ -74,6 +80,8 @@ expire:: have no objects referenced by the MIDX (with the exception of `.keep` packs and cruft packs). Rewrite the MIDX file afterward to remove all references to these pack-files. ++ +NOTE: this mode is incompatible with incremental MIDX files. repack:: Create a new pack-file containing objects in small pack-files @@ -95,7 +103,8 @@ repack:: + If `repack.packKeptObjects` is `false`, then any pack-files with an associated `.keep` file will not be selected for the batch to repack. - ++ +NOTE: this mode is incompatible with incremental MIDX files. EXAMPLES -------- diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index c9221a68cc..84022f99d7 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -9,9 +9,9 @@ SYNOPSIS -------- [verse] 'git notes' [list [<object>]] -'git notes' add [-f] [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>] +'git notes' add [-f] [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] 'git notes' copy [-f] ( --stdin | <from-object> [<to-object>] ) -'git notes' append [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>] +'git notes' append [--allow-empty] [--[no-]separator | --separator=<paragraph-break>] [--[no-]stripspace] [-F <file> | -m <msg> | (-c | -C) <object>] [-e] [<object>] 'git notes' edit [--allow-empty] [<object>] [--[no-]stripspace] 'git notes' show [<object>] 'git notes' merge [-v | -q] [-s <strategy> ] <notes-ref> @@ -67,7 +67,9 @@ add:: the existing notes will be opened in the editor (like the `edit` subcommand). If you specify multiple `-m` and `-F`, a blank line will be inserted between the messages. Use the `--separator` - option to insert other delimiters. + option to insert other delimiters. You can use `-e` to edit and + fine-tune the message(s) supplied from `-m` and `-F` options + interactively (using an editor) before adding the note. copy:: Copy the notes for the first object onto the second object (defaults to @@ -93,6 +95,8 @@ append:: an existing note, a blank line is added before each new message as an inter-paragraph separator. The separator can be customized with the `--separator` option. + Edit the notes to be appended given by `-m` and `-F` options with + `-e` interactively (using an editor) before appending the note. edit:: Edit the notes for a given object (defaults to HEAD). diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 74df345f9e..b18cdbc023 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -737,7 +737,7 @@ The 'apply' backend works by creating a sequence of patches (by calling `format-patch` internally), and then applying the patches in sequence (calling `am` internally). Patches are composed of multiple hunks, each with line numbers, a context region, and the actual changes. The -line numbers have to be taken with some fuzz, since the other side +line numbers have to be taken with some offset, since the other side will likely have inserted or deleted lines earlier in the file. The context region is meant to help find how to adjust the line numbers in order to apply the changes to the right lines. However, if multiple diff --git a/Documentation/git-refs.txt b/Documentation/git-refs.txt index 5b99e04385..ce31f93061 100644 --- a/Documentation/git-refs.txt +++ b/Documentation/git-refs.txt @@ -10,6 +10,7 @@ SYNOPSIS -------- [verse] 'git refs migrate' --ref-format=<format> [--dry-run] +'git refs verify' [--strict] [--verbose] DESCRIPTION ----------- @@ -22,6 +23,9 @@ COMMANDS migrate:: Migrate ref store between different formats. +verify:: + Verify reference database consistency. + OPTIONS ------- @@ -39,6 +43,15 @@ include::ref-storage-format.txt[] can be used to double check that the migration works as expected before performing the actual migration. +The following options are specific to 'git refs verify': + +--strict:: + Enable stricter error checking. This will cause warnings to be + reported as errors. See linkgit:git-fsck[1]. + +--verbose:: + When verifying the reference database consistency, be chatty. + KNOWN LIMITATIONS ----------------- diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index c5d664f451..bc3ef45acb 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -12,6 +12,7 @@ SYNOPSIS 'git send-email' [<options>] (<file>|<directory>)... 'git send-email' [<options>] <format-patch-options> 'git send-email' --dump-aliases +'git send-email' --translate-aliases DESCRIPTION @@ -413,6 +414,12 @@ exists when 'git send-email' is asked to add it (especially note that Failure to do so may not produce the expected result in the recipient's MUA. +--[no-]mailmap:: + Use the mailmap file (see linkgit:gitmailmap[5]) to map all + addresses to their canonical real name and email address. Additional + mailmap data specific to git-send-email may be provided using the + `sendemail.mailmap.file` or `sendemail.mailmap.blob` configuration + values. Defaults to `sendemail.mailmap`. Administering ~~~~~~~~~~~~~ @@ -475,6 +482,12 @@ Information that this only includes the alias name and not its expanded email addresses. See 'sendemail.aliasesFile' for more information about aliases. +--translate-aliases:: + Instead of the normal operation, read from standard input and + interpret each line as an email alias. Translate it according to the + configured alias file(s). Output each translated name and email + address to standard output, one per line. See 'sendemail.aliasFile' + for more information about aliases. CONFIGURATION ------------- diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index ca0347a37b..87d8e0f0c5 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -34,7 +34,7 @@ COMMANDS With no arguments, shows the status of existing submodules. Several subcommands are available to perform operations on the submodules. -add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]:: +add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--ref-format <format>] [--depth <depth>] [--] <repository> [<path>]:: Add the given repository as a submodule at the given path to the changeset to be committed next to the current project: the current project is termed the "superproject". @@ -71,6 +71,9 @@ submodule repositories will be kept together in the same relative location, and only the superproject's URL needs to be provided. git-submodule will correctly locate the submodule using the relative URL in `.gitmodules`. ++ +If `--ref-format <format>` is specified, the ref storage format of newly +cloned submodules will be set accordingly. status [--cached] [--recursive] [--] [<path>...]:: Show the status of the submodules. This will print the SHA-1 of the @@ -136,7 +139,7 @@ If you really want to remove a submodule from the repository and commit that use linkgit:git-rm[1] instead. See linkgit:gitsubmodules[7] for removal options. -update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--depth <depth>] [--recursive] [--jobs <n>] [--[no-]single-branch] [--filter <filter-spec>] [--] [<path>...]:: +update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--ref-format <format>] [--depth <depth>] [--recursive] [--jobs <n>] [--[no-]single-branch] [--filter <filter-spec>] [--] [<path>...]:: + -- Update the registered submodules to match what the superproject @@ -185,6 +188,9 @@ submodule with the `--init` option. If `--recursive` is specified, this command will recurse into the registered submodules, and update any nested submodules within. +If `--ref-format <format>` is specified, the ref storage format of newly +cloned submodules will be set accordingly. + If `--filter <filter-spec>` is specified, the given partial clone filter will be applied to the submodule. See linkgit:git-rev-list[1] for details on filter specifications. diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 43c68c2ec4..bcf7d84a87 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -431,14 +431,14 @@ Any other arguments are passed directly to 'git log' independently of 'git svn' functions. 'create-ignore':: - Recursively finds the svn:ignore property on directories and - creates matching .gitignore files. The resulting files are staged to - be committed, but are not committed. Use -r/--revision to refer to a - specific revision. + Recursively finds the svn:ignore and svn:global-ignores properties + on directories and creates matching .gitignore files. The resulting + files are staged to be committed, but are not committed. Use + -r/--revision to refer to a specific revision. 'show-ignore':: - Recursively finds and lists the svn:ignore property on - directories. The output is suitable for appending to + Recursively finds and lists the svn:ignore and svn:global-ignores + properties on directories. The output is suitable for appending to the $GIT_DIR/info/exclude file. 'mkdirs':: @@ -871,7 +871,7 @@ Tracking and contributing to the trunk of a Subversion-managed project # Now commit your changes (that were committed previously using Git) to SVN, # as well as automatically updating your working HEAD: git svn dcommit -# Append svn:ignore settings to the default Git exclude file: +# Append svn:ignore and svn:global-ignores settings to the default Git exclude file: git svn show-ignore >> .git/info/exclude ------------------------------------------------------------------------ diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt index 761b154bcb..33ca381fde 100644 --- a/Documentation/git-symbolic-ref.txt +++ b/Documentation/git-symbolic-ref.txt @@ -73,6 +73,10 @@ default. symbolic ref were printed correctly, with status 1 if the requested name is not a symbolic ref, or 128 if another error occurs. +SEE ALSO +-------- +linkgit:git-update-ref[1] + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index afcf33cf60..9e6935d38d 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -25,37 +25,16 @@ value is <old-oid>. You can specify 40 "0" or an empty string as <old-oid> to make sure that the ref you are creating does not exist. -It also allows a "ref" file to be a symbolic pointer to another -ref file by starting with the four-byte header sequence of -"ref:". - -More importantly, it allows the update of a ref file to follow -these symbolic pointers, whether they are symlinks or these -"regular file symbolic refs". It follows *real* symlinks only -if they start with "refs/": otherwise it will just try to read -them and update them as a regular file (i.e. it will allow the -filesystem to follow them, but will overwrite such a symlink to -somewhere else with a regular filename). +The final arguments are object names; this command without any options +does not support updating a symbolic ref to point to another ref (see +linkgit:git-symbolic-ref[1]). But `git update-ref --stdin` does have +the `symref-*` commands so that regular refs and symbolic refs can be +committed in the same transaction. If --no-deref is given, <ref> itself is overwritten, rather than the result of following the symbolic pointers. -In general, using - - git update-ref HEAD "$head" - -should be a _lot_ safer than doing - - echo "$head" > "$GIT_DIR/HEAD" - -both from a symlink following standpoint *and* an error checking -standpoint. The "refs/" rule for symlinks means that symlinks -that point to "outside" the tree are safe: they'll be followed -for reading but not for writing (so we'll never write through a -ref symlink to some other tree, if you have copied a whole -archive by creating a symlink tree). - -With `-d` flag, it deletes the named <ref> after verifying it +With `-d`, it deletes the named <ref> after verifying that it still contains <old-oid>. With `--stdin`, update-ref reads instructions from standard input and @@ -114,11 +93,11 @@ update:: ref does not exist before the update. create:: - Create <ref> with <new-oid> after verifying it does not + Create <ref> with <new-oid> after verifying that it does not exist. The given <new-oid> may not be zero. delete:: - Delete <ref> after verifying it exists with <old-oid>, if + Delete <ref> after verifying that it exists with <old-oid>, if given. If given, <old-oid> may not be zero. symref-update:: @@ -131,11 +110,11 @@ verify:: <old-oid> is zero or missing, the ref must not exist. symref-create: - Create symbolic ref <ref> with <new-target> after verifying + Create symbolic ref <ref> with <new-target> after verifying that it does not exist. symref-delete:: - Delete <ref> after verifying it exists with <old-target>, if given. + Delete <ref> after verifying that it exists with <old-target>, if given. symref-verify:: Verify symbolic <ref> against <old-target> but do not change it. @@ -200,6 +179,21 @@ An update will fail (without changing <ref>) if the current user is unable to create a new log file, append to the existing log file or does not have committer information available. +NOTES +----- + +Symbolic refs were initially implemented using symbolic links. This is +now deprecated since not all filesystems support symbolic links. + +This command follows *real* symlinks only if they start with "refs/": +otherwise it will just try to read them and update them as a regular +file (i.e. it will allow the filesystem to follow them, but will +overwrite such a symlink to somewhere else with a regular filename). + +SEE ALSO +-------- +linkgit:git-symbolic-ref[1] + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 2a240f53ba..8340b7f028 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -157,7 +157,7 @@ will reestablish the connection. If multiple linked worktrees are moved, running `repair` from any worktree with each tree's new `<path>` as an argument, will reestablish the connection to all the specified paths. + -If both the main worktree and linked worktrees have been moved manually, +If both the main worktree and linked worktrees have been moved or copied manually, then running `repair` in the main worktree and specifying the new `<path>` of each linked worktree will reestablish all connections in both directions. @@ -216,6 +216,14 @@ To remove a locked worktree, specify `--force` twice. This can also be set up as the default behaviour by using the `worktree.guessRemote` config option. +--[no-]relative-paths:: + Link worktrees using relative paths or absolute paths (default). + Overrides the `worktree.useRelativePaths` config option, see + linkgit:git-config[1]. ++ +With `repair`, the linking files will be updated if there's an absolute/relative +mismatch, even if the links are correct. + --[no-]track:: When creating a new branch, if `<commit-ish>` is a branch, mark it as "upstream" from the new branch. This is the diff --git a/Documentation/git.txt b/Documentation/git.txt index 4489e2297a..d15a869762 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -1027,6 +1027,17 @@ standard output. adequate and support for it is likely to be removed in the foreseeable future (along with the variable). +`GIT_ADVICE`:: + If set to `0`, then disable all advice messages. These messages are + intended to provide hints to human users that may help them get out of + problematic situations or take advantage of new features. Users can + disable individual messages using the `advice.*` config keys. These + messages may be disruptive to tools that execute Git processes, so this + variable is available to disable the messages. (The `--no-advice` + global option is also available, but old Git versions may fail when + this option is not understood. The environment variable will be ignored + by Git versions that do not understand it.) + Discussion[[Discussion]] ------------------------ diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt index 7c709324ba..bd62cbd043 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.txt @@ -90,6 +90,15 @@ scripting Git: for long options. An option that takes optional option-argument must be written in the 'stuck' form. + * Despite the above suggestion, when Arg is a path relative to the + home directory of a user, e.g. ~/directory/file or ~u/d/f, you + may want to use the separate form, e.g. `git foo --file ~/mine`, + not `git foo --file=~/mine`. The shell will expand `~/` in the + former to your home directory, but most shells keep the tilde in + the latter. Some of our commands know how to tilde-expand the + option value even when given in the stuck form, but not all of + them do. + * When you give a revision parameter to a command, make sure the parameter is not ambiguous with a name of a file in the work tree. E.g. do not write `git log -1 HEAD` but write `git log -1 HEAD --`; the former will not work diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt index 71dd19731a..35a7452c8f 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.txt @@ -242,6 +242,12 @@ Here are some example specifications: [credential] helper = "foo --bar='whitespace arg'" +# store helper (discouraged) with custom location for the db file; +# use `--file ~/.git-secret.txt`, rather than `--file=~/.git-secret.txt`, +# to allow the shell to expand tilde to the home directory. +[credential] + helper = "store --file ~/.git-secret.txt" + # you can also use an absolute path, which will not use the git wrapper [credential] helper = "/path/to/my/helper --with-arguments" diff --git a/Documentation/gitformat-commit-graph.txt b/Documentation/gitformat-commit-graph.txt index 3e906e8030..14d1631234 100644 --- a/Documentation/gitformat-commit-graph.txt +++ b/Documentation/gitformat-commit-graph.txt @@ -122,7 +122,7 @@ All multi-byte numbers are in network byte order. for commits with corrected commit date offsets that cannot be stored within 31 bits. * Generation Data Overflow chunk is present only when Generation Data - chunk is present and atleast one corrected commit date offset cannot + chunk is present and at least one corrected commit date offset cannot be stored within 31 bits. ==== Extra Edge List (ID: {'E', 'D', 'G', 'E'}) [Optional] diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 06e997131b..0397dec64d 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -415,13 +415,13 @@ post-receive This hook is invoked by linkgit:git-receive-pack[1] when it reacts to `git push` and updates reference(s) in its repository. -It executes on the remote repository once after all the refs have -been updated. +The hook executes on the remote repository once after all the proposed +ref updates are processed and if at least one ref is updated as the +result. -This hook executes once for the receive operation. It takes no -arguments, but gets the same information as the -<<pre-receive,'pre-receive'>> -hook does on its standard input. +The hook takes no arguments. It receives one line on standard input for +each ref that is successfully updated following the same format as the +<<pre-receive,'pre-receive'>> hook. This hook does not affect the outcome of `git receive-pack`, as it is called after the real work is done. @@ -448,6 +448,9 @@ environment variables will not be set. If the client selects to use push options, but doesn't transmit any, the count variable will be set to zero, `GIT_PUSH_OPTION_COUNT=0`. +See the "post-receive" section in linkgit:git-receive-pack[1] for +additional details. + [[post-update]] post-update ~~~~~~~~~~~ diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt index 414bc625d5..1652fef3ae 100644 --- a/Documentation/gitprotocol-v2.txt +++ b/Documentation/gitprotocol-v2.txt @@ -527,8 +527,8 @@ a request. The provided options must not contain a NUL or LF character. - object-format -~~~~~~~~~~~~~~~ +object-format +~~~~~~~~~~~~~ The server can advertise the `object-format` capability with a value `X` (in the form `object-format=X`) to notify the client that the server is able to deal @@ -776,7 +776,7 @@ This would allow for optimizing the common case of servers who'd like to provide one "big bundle" containing only their "main" branch, and/or incremental updates thereof. + -A client receiving such a a response MAY assume that they can skip +A client receiving such a response MAY assume that they can skip 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. diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt index 949cd8a31e..fa8b51daf0 100644 --- a/Documentation/gitrepository-layout.txt +++ b/Documentation/gitrepository-layout.txt @@ -298,6 +298,7 @@ SEE ALSO -------- linkgit:git-init[1], linkgit:git-clone[1], +linkgit:git-config[1], linkgit:git-fetch[1], linkgit:git-pack-refs[1], linkgit:git-gc[1], diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt index 4759408788..f89ad30cf6 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.txt @@ -360,7 +360,7 @@ $ gitk HEAD...FETCH_HEAD This means "show everything that is reachable from either one, but exclude anything that is reachable from both of them". -Please note that these range notation can be used with both `gitk` +Please note that these range notations can be used with both `gitk` and `git log`. After inspecting what Bob did, if there is nothing urgent, Alice may diff --git a/Documentation/gitweb.txt b/Documentation/gitweb.txt index 56d24a30a3..5e2b491ec2 100644 --- a/Documentation/gitweb.txt +++ b/Documentation/gitweb.txt @@ -234,7 +234,7 @@ from the template during repository creation, usually installed in configuration variable, but the file takes precedence. category (or `gitweb.category`):: - Singe line category of a project, used to group projects if + Single line category of a project, used to group projects if `$projects_list_group_categories` is enabled. By default (file and configuration variable absent), uncategorized projects are put in the `$project_list_default_category` category. You can use the diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 42afe04869..575c18f776 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -696,6 +696,11 @@ the `refs/tags/` hierarchy is used to represent local tags.. that each contain very well defined concepts or small incremental yet related changes. +[[def_trailer]]trailer:: + Key-value metadata. Trailers are optionally found at the end of + a commit message. Might be called "footers" or "tags" in other + communities. See linkgit:git-interpret-trailers[1]. + [[def_tree]]tree:: Either a <<def_working_tree,working tree>>, or a <<def_tree_object,tree object>> together with the dependent <<def_blob_object,blob>> and tree objects diff --git a/Documentation/howto/keep-canonical-history-correct.txt b/Documentation/howto/keep-canonical-history-correct.txt index 5f800fd85a..e98f03275e 100644 --- a/Documentation/howto/keep-canonical-history-correct.txt +++ b/Documentation/howto/keep-canonical-history-correct.txt @@ -13,7 +13,7 @@ that appears to be "backwards" from what other project developers expect. This howto presents a suggested integration workflow for maintaining a central repository. -Suppose that that central repository has this history: +Suppose that the central repository has this history: ------------ ---o---o---A diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.txt index 013014bbef..45e2599c5d 100644 --- a/Documentation/howto/maintain-git.txt +++ b/Documentation/howto/maintain-git.txt @@ -37,22 +37,20 @@ The Policy The policy on Integration is informally mentioned in "A Note from the maintainer" message, which is periodically posted to -this mailing list after each feature release is made. +the mailing list after each feature release is made: - Feature releases are numbered as vX.Y.0 and are meant to contain bugfixes and enhancements in any area, including functionality, performance and usability, without regression. - - One release cycle for a feature release is expected to last for - eight to ten weeks. - - - Maintenance releases are numbered as vX.Y.Z and are meant + - Maintenance releases are numbered as vX.Y.Z (0 < Z) and are meant to contain only bugfixes for the corresponding vX.Y.0 feature release and earlier maintenance releases vX.Y.W (W < Z). - - 'master' branch is used to prepare for the next feature + - The 'master' branch is used to prepare for the next feature release. In other words, at some point, the tip of 'master' - branch is tagged with vX.Y.0. + branch is tagged as vX.(Y+1).0, when vX.Y.0 is the latest + feature release. - 'maint' branch is used to prepare for the next maintenance release. After the feature release vX.Y.0 is made, the tip @@ -63,11 +61,28 @@ this mailing list after each feature release is made. - 'next' branch is used to publish changes (both enhancements and fixes) that (1) have worthwhile goal, (2) are in a fairly good shape suitable for everyday use, (3) but have not yet - demonstrated to be regression free. New changes are tested - in 'next' before merged to 'master'. + demonstrated to be regression free. Reviews from contributors on + the mailing list help to make the determination. After a topic + is merged to 'next', it is tested for at least 7 calendar days + before getting merged to 'master'. - 'seen' branch is used to publish other proposed changes that do - not yet pass the criteria set for 'next'. + not yet pass the criteria set for 'next' (see above), but there + is no promise that 'seen' will contain everything. A topic that + had no reviewer reaction may not be picked up. + + - A new topic will first get merged to 'seen', unless it is + trivially correct and clearly urgent, in which case it may be + directly merged to 'next' or even to 'master'. + + - If a topic that was picked up to 'seen' becomes and stays + inactive for 3 calendar weeks without having seen a clear + consensus that it is good enough to be moved to 'next', the + topic may be discarded from 'seen'. Interested parties are + still free to revive the topic. For the purpose of this + guideline, the definition of being "inactive" is that nobody + has discussed the topic, no new iteration of the topic was + posted, and no responses to the review comments were given. - The tips of 'master' and 'maint' branches will not be rewound to allow people to build their own customization on top of them. @@ -86,10 +101,49 @@ this mailing list after each feature release is made. users are encouraged to test it so that regressions and bugs are found before new topics are merged to 'master'. + - When a problem is found in a topic in 'next', the topic is marked + not to be merged to 'master'. Follow-up patches are discussed on + the mailing list and applied to the topic after being reviewed and + then the topic is merged (again) to 'next'. After going through + the usual testing in 'next', the entire (fixed) topic is merged + to 'master'. + + - One release cycle for a feature release is expected to last for + eight to ten weeks. A few "release candidate" releases are + expected to be tagged about a week apart before the final + release, and a "preview" release is tagged about a week before + the first release candidate gets tagged. + + - After the preview release is tagged, topics that were well + reviewed may be merged to 'master' before spending the usual 7 + calendar days in 'next', with the expectation that any bugs in + them can be caught and fixed in the release candidates before + the final release. + + - After the first release candidate is tagged, the contributors are + strongly encouraged to focus on finding and fixing new regressions + introduced during the cycle, over addressing old bugs and any new + features. Topics stop getting merged down from 'next' to 'master', + and new topics stop getting merged to 'next'. Unless they are fixes + to new regressions in the cycle, that is. + + - Soon after a feature release is made, the tip of 'maint' gets + fast-forwarded to point at the release. Topics that have been + kept in 'next' are merged down to 'master' and a new development + cycle starts. + + Note that before v1.9.0 release, the version numbers used to be structured slightly differently. vX.Y.Z were feature releases while vX.Y.Z.W were maintenance releases for vX.Y.Z. +Because most of the lines of code in Git are written by individual +contributors, and contributions come in the form of e-mailed patches +published on the mailing list, the project maintains a mapping from +individual commits to the Message-Id of the e-mail that resulted in +the commit, to help tracking the origin of the changes. The notes +in "refs/notes/amlog" are used for this purpose, and are published +along with the broken-out branches to the maintainer's repository. A Typical Git Day ----------------- @@ -133,6 +187,43 @@ by doing the following: In practice, almost no patch directly goes to 'master' or 'maint'. + Applying the e-mailed patches using "git am" automatically records + the mappings from 'Message-Id' to the applied commit in the "amlog" + notes. Periodically check that this is working with "git show -s + --notes=amlog $commit". + + This mapping is maintained with the aid of the "post-applypatch" + hook found in the 'todo' branch. That hook should be installed + before applying patches. It is also helpful to carry forward any + relevant amlog entries when rebasing, so the following config may + be useful: + + [notes] + rewriteRef = refs/notes/amlog + + Avoid "cherry-pick", as it does not propagate notes by design. Use + either "git commit --amend" or "git rebase" to make corrections to + an existing commit, even for a single-patch topic. + + Make sure that a push refspec for 'refs/notes/amlog' is in the + remote configuration for publishing repositories. A few sample + configurations look like the following: + + [remote "github"] + url = https://github.com/gitster/git + pushurl = github.com:gitster/git.git + mirror + + [remote "github2"] + url = https://github.com/git/git + fetch = +refs/heads/*:refs/remotes/github2/* + pushurl = github.com:git/git.git + push = refs/heads/maint:refs/heads/maint + push = refs/heads/master:refs/heads/master + push = refs/heads/next:refs/heads/next + push = +refs/heads/seen:refs/heads/seen + push = +refs/notes/amlog + - Review the last issue of "What's cooking" message, review the topics ready for merging (topic->master and topic->maint). Use "Meta/cook -w" script (where Meta/ contains a checkout of the @@ -149,6 +240,10 @@ by doing the following: $ git diff ORIG_HEAD.. ;# final review $ make test ;# final review + If the tip of 'master' is updated, also generate the preformatted + documentation and push the out result to git-htmldocs and + git-manpages repositories. + - Handle the remaining patches: - Anything unobvious that is applicable to 'master' (in other @@ -179,12 +274,12 @@ by doing the following: The initial round is done with: $ git checkout ai/topic ;# or "git checkout -b ai/topic master" - $ git am -sc3 mailbox + $ git am -sc3 --whitespace=warn mailbox and replacing an existing topic with subsequent round is done with: $ git checkout master...ai/topic ;# try to reapply to the same base - $ git am -sc3 mailbox + $ git am -sc3 --whitespace=warn mailbox to prepare the new round on a detached HEAD, and then @@ -209,39 +304,59 @@ by doing the following: (trivial typofixes etc. are often squashed directly into the patches that need fixing, without being applied as a separate "SQUASH???" commit), so that they can be removed easily as needed. + The expectation is that the original author will make corrections + in a reroll. + - By now, new topic branches are created and existing topic + branches are updated. The integration branches 'next', 'jch', + and 'seen' need to be updated to contain them. - - Merge maint to master as needed: + - If there are topics that have been merged to 'master' and should + be merged to 'maint', merge them to 'maint', and update the + release notes to the next maintenance release. - $ git checkout master - $ git merge maint - $ make test + - Review the latest issue of "What's cooking" again. Are topics + that have been sufficiently long in 'next' ready to be merged to + 'master'? Are topics we saw earlier and are in 'seen' now got + positive reviews and are ready to be merged to 'next'? - - Merge master to next as needed: + - If there are topics that have been cooking in 'next' long enough + and should be merged to 'master', merge them to 'master', and + update the release notes to the next feature release. - $ git checkout next - $ git merge master - $ make test + - If there were patches directly made on 'maint', merge 'maint' to + 'master'; make sure that the result is what you want. - - Review the last issue of "What's cooking" again and see if topics - that are ready to be merged to 'next' are still in good shape - (e.g. has there any new issue identified on the list with the - series?) + $ git checkout master + $ git merge -m "Sync with 'maint'" --no-log maint + $ git log -p --first-parent ORIG_HEAD.. + $ make test - - Prepare 'jch' branch, which is used to represent somewhere - between 'master' and 'seen' and often is slightly ahead of 'next'. + - Prepare to update the 'jch' branch, which is used to represent + somewhere between 'master' and 'seen' and often is slightly ahead + of 'next', and the 'seen' branch, which is used to hold the rest. $ Meta/Reintegrate master..jch >Meta/redo-jch.sh The result is a script that lists topics to be merged in order to - rebuild 'seen' as the input to Meta/Reintegrate script. Remove - later topics that should not be in 'jch' yet. Add a line that - consists of '### match next' before the name of the first topic - in the output that should be in 'jch' but not in 'next' yet. + rebuild the current 'jch'. Do the same for 'seen'. + + - Review the Meta/redo-jch.sh and Meta/redo-seen.sh scripts. The + former should have a line '### match next'---the idea is that + merging the topics listed before the line on top of 'master' + should result in a tree identical to that of 'next'. - - Now we are ready to start merging topics to 'next'. For each - branch whose tip is not merged to 'next', one of three things can - happen: + - As newly created topics are usually merged near the tip of + 'seen', add them to the end of the Meta/redo-seen.sh script. + Among the topics that were in 'seen', there may be ones that + are not quite ready for 'next' but are getting there. Move + them from Meta/redo-seen.sh to the end of Meta/redo-jch.sh. + The expectation is that you'd use 'jch' as your daily driver + as the first guinea pig, so you should choose carefully. + + - Now we are ready to start rebuilding 'jch' and merging topics to + 'next'. For each branch whose tip is not merged to 'next', one + of three things can happen: - The commits are all next-worthy; merge the topic to next; - The new parts are of mixed quality, but earlier ones are @@ -252,10 +367,12 @@ by doing the following: If a topic that was already in 'next' gained a patch, the script would list it as "ai/topic~1". To include the new patch to the updated 'next', drop the "~1" part; to keep it excluded, do not - touch the line. If a topic that was not in 'next' should be - merged to 'next', add it at the end of the list. Then: + touch the line. + + If a topic that was not in 'next' should be merged to 'next', add + it before the '### match next' line. Then: - $ git checkout -B jch master + $ git checkout --detach master $ sh Meta/redo-jch.sh -c1 to rebuild the 'jch' branch from scratch. "-c1" tells the script @@ -267,26 +384,29 @@ by doing the following: reference to the variable under its old name), in which case prepare an appropriate merge-fix first (see appendix), and rebuild the 'jch' branch from scratch, starting at the tip of - 'master'. + 'master', this time without using "-c1" to merge all topics. - Then do the same to 'next' + Then do the same to 'next'. $ git checkout next $ sh Meta/redo-jch.sh -c1 -e The "-e" option allows the merge message that comes from the history of the topic and the comments in the "What's cooking" to - be edited. The resulting tree should match 'jch' as the same set - of topics are merged on 'master'; otherwise there is a mismerge. - Investigate why and do not proceed until the mismerge is found - and rectified. + be edited. The resulting tree should match 'jch^{/^### match next'}' + as the same set of topics are merged on 'master'; otherwise there + is a mismerge. Investigate why and do not proceed until the mismerge + is found and rectified. + + If 'master' was updated before you started redoing 'next', then - $ git diff jch next + $ git diff 'jch^{/^### match next}' next - Then build the rest of 'jch': + would show differences that went into 'master' (which 'jch' has, + but 'next' does not yet---often it is updates to the release + notes). Merge 'master' back to 'next' if that is the case. - $ git checkout jch - $ sh Meta/redo-jch.sh + $ git merge -m "Sync with 'master'" --no-log master When all is well, clean up the redo-jch.sh script with @@ -296,12 +416,7 @@ by doing the following: merged to 'master'. This may lose '### match next' marker; add it again to the appropriate place when it happens. - - Rebuild 'seen'. - - $ Meta/Reintegrate jch..seen >Meta/redo-seen.sh - - Edit the result by adding new topics that are not still in 'seen' - in the script. Then + - Rebuild 'seen' on top of 'jch'. $ git checkout -B seen jch $ sh Meta/redo-seen.sh @@ -312,7 +427,7 @@ by doing the following: Double check by running - $ git branch --no-merged seen + $ git branch --no-merged seen '??/*' to see there is no unexpected leftover topics. diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index c718f7946f..d79d2f6065 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -25,14 +25,15 @@ endif::git-pull[] + The format of a <refspec> parameter is an optional plus `+`, followed by the source <src>, followed -by a colon `:`, followed by the destination ref <dst>. +by a colon `:`, followed by the destination <dst>. The colon can be omitted when <dst> is empty. <src> is -typically a ref, but it can also be a fully spelled hex object +typically a ref, or a glob pattern with a single `*` that is used +to match a set of refs, but it can also be a fully spelled hex object name. + A <refspec> may contain a `*` in its <src> to indicate a simple pattern match. Such a refspec functions like a glob that matches any ref with the -same prefix. A pattern <refspec> must have a `*` in both the <src> and +pattern. A pattern <refspec> must have one and only one `*` in both the <src> and <dst>. It will map refs to the destination by replacing the `*` with the contents matched from the source. + diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 00ccf68744..459e5a02f5 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -412,7 +412,8 @@ Default mode:: --ancestry-path[=<commit>]:: When given a range of commits to display (e.g. 'commit1..commit2' - or 'commit2 {caret}commit1'), only display commits in that range + or 'commit2 {caret}commit1'), and a commit <commit> in that range, + only display commits in that range that are ancestors of <commit>, descendants of <commit>, or <commit> itself. If no commit is specified, use 'commit1' (the excluded part of the range) as <commit>. Can be passed multiple diff --git a/Documentation/scalar.txt b/Documentation/scalar.txt index 361f51a647..7e4259c674 100644 --- a/Documentation/scalar.txt +++ b/Documentation/scalar.txt @@ -86,6 +86,13 @@ cloning. If the HEAD at the remote did not point at any branch when `<entlistment>/src` directory. Use `--no-src` to place the cloned repository directly in the `<enlistment>` directory. +--[no-]tags:: + By default, `scalar clone` will fetch the tag objects advertised by + the remote and future `git fetch` commands will do the same. Use + `--no-tags` to avoid fetching tags in `scalar clone` and to configure + the repository to avoid fetching tags in the future. To fetch tags after + cloning with `--no-tags`, run `git fetch --tags`. + --[no-]full-clone:: A sparse-checkout is initialized by default. This behavior can be turned off via `--full-clone`. diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt index de5fc25059..5817b18310 100644 --- a/Documentation/technical/api-trace2.txt +++ b/Documentation/technical/api-trace2.txt @@ -128,7 +128,7 @@ yields ------------ $ cat ~/log.event -{"event":"version","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"3","exe":"2.20.1.155.g426c96fcdb"} +{"event":"version","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"4","exe":"2.20.1.155.g426c96fcdb"} {"event":"start","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621027Z","file":"common-main.c","line":39,"t_abs":0.001173,"argv":["git","version"]} {"event":"cmd_name","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621122Z","file":"git.c","line":432,"name":"version","hierarchy":"version"} {"event":"exit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621236Z","file":"git.c","line":662,"t_abs":0.001227,"code":0} @@ -344,7 +344,7 @@ only present on the "start" and "atexit" events. { "event":"version", ... - "evt":"3", # EVENT format version + "evt":"4", # EVENT format version "exe":"2.20.1.155.g426c96fcdb" # git version } ------------ @@ -835,6 +835,19 @@ The "value" field may be an integer or a string. } ------------ +`"printf"`:: + This event logs a human-readable message with no particular formatting + guidelines. ++ +------------ +{ + "event":"printf", + ... + "t_abs":0.015905, # elapsed time in seconds + "msg":"Hello world" # optional +} +------------ + == Example Trace2 API Usage diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt index ed57481089..7102c7c8f5 100644 --- a/Documentation/technical/hash-function-transition.txt +++ b/Documentation/technical/hash-function-transition.txt @@ -148,8 +148,8 @@ Detailed Design Repository format extension ~~~~~~~~~~~~~~~~~~~~~~~~~~~ A SHA-256 repository uses repository format version `1` (see -Documentation/technical/repository-version.txt) with extensions -`objectFormat` and `compatObjectFormat`: +linkgit:gitrepository-layout[5]) with `extensions.objectFormat` and +`extensions.compatObjectFormat` (see linkgit:git-config[1]) set to: [core] repositoryFormatVersion = 1 diff --git a/Documentation/technical/multi-pack-index.txt b/Documentation/technical/multi-pack-index.txt index f2221d2b44..cc063b30be 100644 --- a/Documentation/technical/multi-pack-index.txt +++ b/Documentation/technical/multi-pack-index.txt @@ -61,6 +61,109 @@ Design Details - The MIDX file format uses a chunk-based approach (similar to the commit-graph file) that allows optional data to be added. +Incremental multi-pack indexes +------------------------------ + +As repositories grow in size, it becomes more expensive to write a +multi-pack index (MIDX) that includes all packfiles. To accommodate +this, the "incremental multi-pack indexes" feature allows for combining +a "chain" of multi-pack indexes. + +Each individual component of the chain need only contain a small number +of packfiles. Appending to the chain does not invalidate earlier parts +of the chain, so repositories can control how much time is spent +updating the MIDX chain by determining the number of packs in each layer +of the MIDX chain. + +=== Design state + +At present, the incremental multi-pack indexes feature is missing two +important components: + + - The ability to rewrite earlier portions of the MIDX chain (i.e., to + "compact" some collection of adjacent MIDX layers into a single + MIDX). At present the only supported way of shrinking a MIDX chain + is to rewrite the entire chain from scratch without the `--split` + flag. ++ +There are no fundamental limitations that stand in the way of being able +to implement this feature. It is omitted from the initial implementation +in order to reduce the complexity, but will be added later. + + - Support for reachability bitmaps. The classic single MIDX + implementation does support reachability bitmaps (see the section + titled "multi-pack-index reverse indexes" in + linkgit:gitformat-pack[5] for more details). ++ +As above, there are no fundamental limitations that stand in the way of +extending the incremental MIDX format to support reachability bitmaps. +The design below specifically takes this into account, and support for +reachability bitmaps will be added in a future patch series. It is +omitted from the current implementation for the same reason as above. ++ +In brief, to support reachability bitmaps with the incremental MIDX +feature, the concept of the pseudo-pack order is extended across each +layer of the incremental MIDX chain to form a concatenated pseudo-pack +order. This concatenation takes place in the same order as the chain +itself (in other words, the concatenated pseudo-pack order for a chain +`{$H1, $H2, $H3}` would be the pseudo-pack order for `$H1`, followed by +the pseudo-pack order for `$H2`, followed by the pseudo-pack order for +`$H3`). ++ +The layout will then be extended so that each layer of the incremental +MIDX chain can write a `*.bitmap`. The objects in each layer's bitmap +are offset by the number of objects in the previous layers of the chain. + +=== File layout + +Instead of storing a single `multi-pack-index` file (with an optional +`.rev` and `.bitmap` extension) in `$GIT_DIR/objects/pack`, incremental +MIDXs are stored in the following layout: + +---- +$GIT_DIR/objects/pack/multi-pack-index.d/ +$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-chain +$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H1.midx +$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H2.midx +$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H3.midx +---- + +The `multi-pack-index-chain` file contains a list of the incremental +MIDX files in the chain, in order. The above example shows a chain whose +`multi-pack-index-chain` file would contain the following lines: + +---- +$H1 +$H2 +$H3 +---- + +The `multi-pack-index-$H1.midx` file contains the first layer of the +multi-pack-index chain. The `multi-pack-index-$H2.midx` file contains +the second layer of the chain, and so on. + +When both an incremental- and non-incremental MIDX are present, the +non-incremental MIDX is always read first. + +=== Object positions for incremental MIDXs + +In the original multi-pack-index design, we refer to objects via their +lexicographic position (by object IDs) within the repository's singular +multi-pack-index. In the incremental multi-pack-index design, we refer +to objects via their index into a concatenated lexicographic ordering +among each component in the MIDX chain. + +If `objects_nr()` is a function that returns the number of objects in a +given MIDX layer, then the index of an object at lexicographic position +`i` within, say, $H3 is defined as: + +---- +objects_nr($H2) + objects_nr($H1) + i +---- + +(in the C implementation, this is often computed as `i + +m->num_objects_in_base`). + Future Work ----------- diff --git a/Documentation/technical/partial-clone.txt b/Documentation/technical/partial-clone.txt index cd948b0072..bf5ec5c82d 100644 --- a/Documentation/technical/partial-clone.txt +++ b/Documentation/technical/partial-clone.txt @@ -102,7 +102,7 @@ or commits that reference missing trees. - On the client a repository extension is added to the local config to prevent older versions of git from failing mid-operation because of missing objects that they cannot handle. - See "extensions.partialClone" in Documentation/technical/repository-version.txt" + See `extensions.partialClone` in linkgit:git-config[1]. Handling Missing Objects diff --git a/Documentation/technical/platform-support.txt b/Documentation/technical/platform-support.txt new file mode 100644 index 0000000000..0a2fb28d62 --- /dev/null +++ b/Documentation/technical/platform-support.txt @@ -0,0 +1,190 @@ +Platform Support Policy +======================= + +Git has a history of providing broad "support" for exotic platforms and older +platforms, without an explicit commitment. Stakeholders of these platforms may +want a more predictable support commitment. This is only possible when platform +stakeholders supply Git developers with adequate tooling, so we can test for +compatibility or develop workarounds for platform-specific quirks on our own. +Various levels of platform-specific tooling will allow us to make more solid +commitments around Git's compatibility with that platform. + +Note that this document is about maintaining existing support for a platform +that has generally worked in the past; for adding support to a platform which +doesn't generally work with Git, the stakeholders for that platform are expected +to do the bulk of that work themselves. We will consider such patches if they +don't make life harder for other supported platforms or for Git contributors. +Some contributors may volunteer to help with the initial or continued support, +but that's not a given. Support work which is too intrusive or difficult for the +project to maintain may still not be accepted. + +Minimum Requirements +-------------------- + +The rest of this doc describes best practices for platforms to make themselves +easy to support. However, before considering support at all, platforms need to +meet the following minimum requirements: + +* Has C99 or C11 + +* Uses versions of dependencies which are generally accepted as stable and + supportable, e.g., in line with the version used by other long-term-support + distributions + +* Has active security support (taking security releases of dependencies, etc) + +These requirements are a starting point, and not sufficient on their own for the +Git community to be enthusiastic about supporting your platform. Maintainers of +platforms which do meet these requirements can follow the steps below to make it +more likely that Git updates will respect the platform's needs. + +Compatible by next release +-------------------------- + +To increase probability that compatibility issues introduced in a release +will be fixed in a later release: + +* You should send a bug report as soon as you notice the breakage on your + platform. The sooner you notice, the better; watching `seen` means you can + notice problems before they are considered "done with review"; whereas + watching `master` means the stable branch could break for your platform, but + you have a decent chance of avoiding a tagged release breaking you. See "The + Policy" in link:../howto/maintain-git.html["How to maintain Git"] for an + overview of which branches are used in the Git project, and how. + +* The bug report should include information about what platform you are using. + +* You should also use linkgit:git-bisect[1] and determine which commit + introduced the breakage. + +* Please include any information you have about the nature of the breakage: is + it a memory alignment issue? Is an underlying library missing or broken for + your platform? Is there some quirk about your platform which means typical + practices (like malloc) behave strangely? + +* If possible, build Git from the exact same source both for your platform and + for a mainstream platform, to see if the problem you noticed appears only + on your platform. If the problem appears in both, then it's not a + compatibility issue, but we of course appreciate hearing about it in a bug + report anyway, to benefit users of every platform. If it appears only on your + platform, mention clearly that it is a compatibility issue in your report. + +* Once we begin to fix the issue, please work closely with the contributor + working on it to test the proposed fix against your platform. + +Example: NonStop +https://lore.kernel.org/git/01bd01da681a$b8d70a70$2a851f50$@nexbridge.com/[reports +problems] when they're noticed. + +Compatible on `master` and releases +----------------------------------- + +To make sure all stable builds and regular releases work for your platform the +first time, help us avoid breaking `master` for your platform: + +* You should run regular tests against the `next` branch and + publish breakage reports to the mailing list immediately when they happen. + +** Ideally, these tests should run daily. They must run more often than + weekly, as topics generally spend at least 7 days in `next` before graduating + to `master`, and it takes time to put the brakes on a patch once it lands in + `next`. + +** You may want to ask to join the mailto:git-security@googlegroups.com[security + mailing list] in order to run tests against the fixes proposed there, too. + +* It may make sense to automate these; if you do, make sure they are not noisy + (you don't need to send a report when everything works, only when something + breaks; you don't need to send repeated reports for the same breakage night + after night). + +* Breakage reports should be actionable - include clear error messages that can + help developers who may not have access to test directly on your platform. + +* You should use git-bisect and determine which commit introduced the breakage; + if you can't do this with automation, you should do this yourself manually as + soon as you notice a breakage report was sent. + +* You should either: + +** Provide on-demand access to your platform to a trusted developer working to + fix the issue, so they can test their fix, OR + +** Work closely with the developer fixing the issue; the turnaround to check + that their proposed fix works for your platform should be fast enough that it + doesn't hinder the developer working on that fix. Slow testing turnarounds + may cause the fix to miss the next release, or the developer may lose + interest in working on the fix at all. + +Example: +https://lore.kernel.org/git/CAHd-oW6X4cwD_yLNFONPnXXUAFPxgDoccv2SOdpeLrqmHCJB4Q@mail.gmail.com/[AIX] +provides a build farm and runs tests against release candidates. + +Compatible on `next` +-------------------- + +To avoid reactive debugging and fixing when changes hit a release or stable, you +can aim to ensure `next` always works for your platform. (See "The Policy" in +link:../howto/maintain-git.html["How to maintain Git"] for an overview of how +`next` is used in the Git project.) To do that: + +* You should add a runner for your platform to the GitHub Actions or GitLab CI + suite. This suite is run when any Git developer proposes a new patch, and + having a runner for your platform/configuration means every developer will + know if they break you, immediately. + +** If adding it to an existing CI suite is infeasible (due to architecture + constraints or for performance reasons), any other method which runs as + automatically and quickly as possible works, too. For example, a service + which snoops on the mailing list and automatically runs tests on new [PATCH] + emails, replying to the author with the results, would also be within the + spirit of this requirement. + +* If you rely on Git avoiding a specific pattern that doesn't work well with + your platform (like a certain malloc pattern), raise it on the mailing list. + We'll work case-by-case to look for a solution that doesn't unnecessarily + constrain other platforms to keep compatibility with yours. + +* If you rely on some configuration or behavior, add a test for it. Untested + behavior is subject to breakage at any time. + +** Clearly label these tests as necessary for platform compatibility. Add them + to an isolated compatibility-related test suite, like a new t* file or unit + test suite, so that they're easy to remove when compatibility is no longer + required. If the specific compatibility need is gated behind an issue with + another project, link to documentation of that issue (like a bug or email + thread) to make it easier to tell when that compatibility need goes away. + +** Include a comment with an expiration date for these tests no more than 1 year + from now. You can update the expiration date if your platform still needs + that assurance down the road, but we need to know you still care about that + compatibility case and are working to make it unnecessary. + +Example: We run our +https://git.kernel.org/pub/scm/git/git.git/tree/.github/workflows/main.yml[CI +suite] on Windows, Ubuntu, Mac, and others. + +Getting help writing platform support patches +--------------------------------------------- + +In general, when sending patches to fix platform support problems, follow +these guidelines to make sure the patch is reviewed with the appropriate level +of urgency: + +* Clearly state in the commit message that you are fixing a platform breakage, + and for which platform. + +* Use the CI and test suite to ensure that the fix for your platform doesn't + break other platforms. + +* If possible, add a test ensuring this regression doesn't happen again. If + it's not possible to add a test, explain why in the commit message. + +Platform Maintainers +-------------------- + +If you maintain a platform, or Git for that platform, and intend to work with +the Git project to ensure compatibility, please send a patch to add yourself to +this list. + +NonStop: Randall S. Becker <rsbecker@nexbridge.com> diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt index 47281420fc..b9bb81a81f 100644 --- a/Documentation/technical/repository-version.txt +++ b/Documentation/technical/repository-version.txt @@ -65,44 +65,6 @@ Note that if no extensions are specified in the config file, then provides no benefit, and makes the repository incompatible with older implementations of git). -This document will serve as the master list for extensions. Any -implementation wishing to define a new extension should make a note of -it here, in order to claim the name. - -The defined extensions are: - -==== `noop` - -This extension does not change git's behavior at all. It is useful only -for testing format-1 compatibility. - -==== `preciousObjects` - -When the config key `extensions.preciousObjects` is set to `true`, -objects in the repository MUST NOT be deleted (e.g., by `git-prune` or -`git repack -d`). - -==== `partialClone` - -When the config key `extensions.partialClone` is set, it indicates -that the repo was created with a partial clone (or later performed -a partial fetch) and that the remote may have omitted sending -certain unwanted objects. Such a remote is called a "promisor remote" -and it promises that all such omitted objects can be fetched from it -in the future. - -The value of this key is the name of the promisor remote. - -==== `worktreeConfig` - -If set, by default "git config" reads from both "config" and -"config.worktree" files from GIT_DIR in that order. In -multiple working directory mode, "config" file is shared while -"config.worktree" is per-working directory (i.e., it's in -GIT_COMMON_DIR/worktrees/<id>/config.worktree) - -==== `refStorage` - -Specifies the file format for the ref database. The valid values are -`files` (loose references with a packed-refs file) and `reftable` (see -Documentation/technical/reftable.txt). +The defined extensions are given in the `extensions.*` section of +linkgit:git-config[1]. Any implementation wishing to define a new +extension should make a note of it there, in order to claim the name. diff --git a/Documentation/technical/sparse-checkout.txt b/Documentation/technical/sparse-checkout.txt index fa0d01cbda..d968659354 100644 --- a/Documentation/technical/sparse-checkout.txt +++ b/Documentation/technical/sparse-checkout.txt @@ -287,7 +287,7 @@ everything behaves like a dense checkout with a few exceptions (e.g. branch checkouts and switches write fewer things, knowing the VFS will lazily write the rest on an as-needed basis). -Since there is no publically available VFS-related code for folks to try, +Since there is no publicly available VFS-related code for folks to try, the number of folks who can test such a usecase is limited. The primary reason to note the Behavior C usecase is that as we fix things diff --git a/Documentation/technical/unit-tests.txt b/Documentation/technical/unit-tests.txt index 206037ffb1..5a432b7b29 100644 --- a/Documentation/technical/unit-tests.txt +++ b/Documentation/technical/unit-tests.txt @@ -203,6 +203,7 @@ GitHub / GitLab stars to estimate this. :criterion: https://github.com/Snaipe/Criterion[Criterion] :c-tap: https://github.com/rra/c-tap-harness/[C TAP] :check: https://libcheck.github.io/check/[Check] +:clar: https://github.com/clar-test/clar[Clar] [format="csv",options="header",width="33%",subs="specialcharacters,attributes,quotes,macros"] |===== @@ -212,6 +213,7 @@ Framework,"<<license,License>>","<<vendorable-or-ubiquitous,Vendorable or ubiqui {criterion},{mit},{false},{partial},{true},{true},{true},{true},{true},{false},{true},19,1800 {c-tap},{expat},{true},{partial},{partial},{true},{false},{true},{false},{false},{false},4,33 {check},{lgpl},{false},{partial},{true},{true},{true},{false},{false},{false},{true},17,973 +{clar},{isc},{false},{partial},{true},{true},{true},{true},{false},{false},{true},1,192 |===== === Additional framework candidates diff --git a/Documentation/urls.txt b/Documentation/urls.txt index 7cec85aef1..9c871e716a 100644 --- a/Documentation/urls.txt +++ b/Documentation/urls.txt @@ -10,19 +10,19 @@ Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them). -The native transport (i.e. git:// URL) does no authentication and +The native transport (i.e. `git://` URL) does no authentication and should be used with caution on unsecured networks. The following syntaxes may be used with them: -- ++ssh://++{startsb}__<user>__++@++{endsb}__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__ -- ++git://++__<host>__{startsb}:__<port>__{endsb}++/++__<path-to-git-repo>__ -- ++http++{startsb}++s++{endsb}++://++__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__ -- ++ftp++{startsb}++s++{endsb}++://++__<host>__{startsb}++:++__<port>__{endsb}++/++__<path-to-git-repo>__ +- `ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>` +- `git://<host>[:<port>]/<path-to-git-repo>` +- `http[s]://<host>[:<port>]/<path-to-git-repo>` +- `ftp[s]://<host>[:<port>]/<path-to-git-repo>` An alternative scp-like syntax may also be used with the ssh protocol: -- {startsb}__<user>__++@++{endsb}__<host>__++:/++__<path-to-git-repo>__ +- `[<user>@]<host>:/<path-to-git-repo>` This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a @@ -30,17 +30,17 @@ colon. For example the local path `foo:bar` could be specified as an absolute path or `./foo:bar` to avoid being misinterpreted as an ssh url. -The ssh and git protocols additionally support ++~++__<username>__ expansion: +The ssh and git protocols additionally support `~<username>` expansion: -- ++ssh://++{startsb}__<user>__++@++{endsb}__<host>__{startsb}++:++__<port>__{endsb}++/~++__<user>__++/++__<path-to-git-repo>__ -- ++git://++__<host>__{startsb}++:++__<port>__{endsb}++/~++__<user>__++/++__<path-to-git-repo>__ -- {startsb}__<user>__++@++{endsb}__<host>__++:~++__<user>__++/++__<path-to-git-repo>__ +- `ssh://[<user>@]<host>[:<port>]/~<user>/<path-to-git-repo>` +- `git://<host>[:<port>]/~<user>/<path-to-git-repo>` +- `[<user>@]<host>:~<user>/<path-to-git-repo>` For local repositories, also supported by Git natively, the following syntaxes may be used: - `/path/to/repo.git/` -- ++file:///path/to/repo.git/++ +- `file:///path/to/repo.git/` ifndef::git-clone[] These two syntaxes are mostly equivalent, except when cloning, when @@ -57,11 +57,11 @@ endif::git-clone[] accept a suitable bundle file. See linkgit:git-bundle[1]. When Git doesn't know how to handle a certain transport protocol, it -attempts to use the `remote-`{empty}__<transport>__ remote helper, if one +attempts to use the `remote-<transport>` remote helper, if one exists. To explicitly request a remote helper, the following syntax may be used: -- _<transport>_::__<address>__ +- `<transport>::<address>` where _<address>_ may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 50dcc77cad..78e8631f67 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.46.0-rc2 +DEF_VER=v2.47.GIT LF=' ' @@ -119,7 +119,7 @@ Issues of note: - A POSIX-compliant shell is required to run some scripts needed for everyday use (e.g. "bisect", "request-pull"). - - "Perl" version 5.8.1 or later is needed to use some of the + - "Perl" version 5.26.0 or later is needed to use some of the features (e.g. sending patches using "git send-email", interacting with svn repositories with "git svn"). If you can live without these, use NO_PERL. Note that recent releases of @@ -129,17 +129,12 @@ Issues of note: itself, e.g. Digest::MD5, File::Spec, File::Temp, Net::Domain, Net::SMTP, and Time::HiRes. - - git-imap-send needs the OpenSSL library to talk IMAP over SSL if - you are using libcurl older than 7.34.0. Otherwise you can use - NO_OPENSSL without losing git-imap-send. - - "libcurl" library is used for fetching and pushing repositories over http:// or https://, as well as by - git-imap-send if the curl version is >= 7.34.0. If you do - not need that functionality, use NO_CURL to build without - it. + git-imap-send. If you do not need that functionality, + use NO_CURL to build without it. - Git requires version "7.21.3" or later of "libcurl" to build + Git requires version "7.61.0" or later of "libcurl" to build without NO_CURL. This version requirement may be bumped in the future. @@ -385,6 +385,10 @@ include shared.mak # supports calling _NSGetExecutablePath to retrieve the path of the running # executable. # +# When using RUNTIME_PREFIX, define HAVE_ZOS_GET_EXECUTABLE_PATH if your platform +# supports calling __getprogramdir and getprogname to retrieve the path of the +# running executable. +# # When using RUNTIME_PREFIX, define HAVE_WPGMPTR if your platform offers # the global variable _wpgmptr containing the absolute path of the current # executable (this is the case on Windows). @@ -517,6 +521,10 @@ include shared.mak # Define APPLE_COMMON_CRYPTO_SHA1 to use Apple's CommonCrypto for # SHA-1. # +# Define the same Makefile knobs as above, but suffixed with _UNSAFE to +# use the corresponding implementations for unsafe SHA-1 hashing for +# non-cryptographic purposes. +# # If don't enable any of the *_SHA1 settings in this section, Git will # default to its built-in sha1collisiondetection library, which is a # collision-detecting sha1 This is slower, but may detect attempted @@ -808,7 +816,6 @@ TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o TEST_BUILTINS_OBJS += test-match-trees.o TEST_BUILTINS_OBJS += test-mergesort.o TEST_BUILTINS_OBJS += test-mktemp.o -TEST_BUILTINS_OBJS += test-oid-array.o TEST_BUILTINS_OBJS += test-online-cpus.o TEST_BUILTINS_OBJS += test-pack-mtimes.o TEST_BUILTINS_OBJS += test-parse-options.o @@ -843,7 +850,6 @@ TEST_BUILTINS_OBJS += test-submodule.o TEST_BUILTINS_OBJS += test-subprocess.o TEST_BUILTINS_OBJS += test-trace2.o TEST_BUILTINS_OBJS += test-truncate.o -TEST_BUILTINS_OBJS += test-urlmatch-normalization.o TEST_BUILTINS_OBJS += test-userdiff.o TEST_BUILTINS_OBJS += test-wildmatch.o TEST_BUILTINS_OBJS += test-windows-named-pipe.o @@ -909,11 +915,12 @@ TEST_SHELL_PATH = $(SHELL_PATH) LIB_FILE = libgit.a XDIFF_LIB = xdiff/lib.a REFTABLE_LIB = reftable/libreftable.a -REFTABLE_TEST_LIB = reftable/libreftable_test.a GENERATED_H += command-list.h GENERATED_H += config-list.h GENERATED_H += hook-list.h +GENERATED_H += $(UNIT_TEST_DIR)/clar-decls.h +GENERATED_H += $(UNIT_TEST_DIR)/clar.suite .PHONY: generated-hdrs generated-hdrs: $(GENERATED_H) @@ -1331,24 +1338,41 @@ THIRD_PARTY_SOURCES += compat/poll/% THIRD_PARTY_SOURCES += compat/regex/% THIRD_PARTY_SOURCES += sha1collisiondetection/% THIRD_PARTY_SOURCES += sha1dc/% +THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% +THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% + +CLAR_TEST_SUITES += ctype +CLAR_TEST_SUITES += strvec +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 -UNIT_TEST_PROGRAMS += t-ctype UNIT_TEST_PROGRAMS += t-example-decorate UNIT_TEST_PROGRAMS += t-hash +UNIT_TEST_PROGRAMS += t-hashmap UNIT_TEST_PROGRAMS += t-mem-pool +UNIT_TEST_PROGRAMS += t-oid-array UNIT_TEST_PROGRAMS += t-oidmap UNIT_TEST_PROGRAMS += t-oidtree UNIT_TEST_PROGRAMS += t-prio-queue UNIT_TEST_PROGRAMS += t-reftable-basics +UNIT_TEST_PROGRAMS += t-reftable-block +UNIT_TEST_PROGRAMS += t-reftable-merged +UNIT_TEST_PROGRAMS += t-reftable-pq +UNIT_TEST_PROGRAMS += t-reftable-reader +UNIT_TEST_PROGRAMS += t-reftable-readwrite UNIT_TEST_PROGRAMS += t-reftable-record +UNIT_TEST_PROGRAMS += t-reftable-stack +UNIT_TEST_PROGRAMS += t-reftable-tree UNIT_TEST_PROGRAMS += t-strbuf UNIT_TEST_PROGRAMS += t-strcmp-offset -UNIT_TEST_PROGRAMS += t-strvec 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 = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(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 GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE) @@ -1376,7 +1400,7 @@ PTHREAD_CFLAGS = # For the 'sparse' target SPARSE_FLAGS ?= -std=gnu99 -SP_EXTRA_FLAGS = -Wno-universal-initializer +SP_EXTRA_FLAGS = # For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets SANITIZE_LEAK = @@ -1977,6 +2001,27 @@ endif endif endif +ifdef OPENSSL_SHA1_UNSAFE +ifndef OPENSSL_SHA1 + EXTLIBS += $(LIB_4_CRYPTO) + BASIC_CFLAGS += -DSHA1_OPENSSL_UNSAFE +endif +else +ifdef BLK_SHA1_UNSAFE +ifndef BLK_SHA1 + LIB_OBJS += block-sha1/sha1.o + BASIC_CFLAGS += -DSHA1_BLK_UNSAFE +endif +else +ifdef APPLE_COMMON_CRYPTO_SHA1_UNSAFE +ifndef APPLE_COMMON_CRYPTO_SHA1 + COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL + BASIC_CFLAGS += -DSHA1_APPLE_UNSAFE +endif +endif +endif +endif + ifdef OPENSSL_SHA256 EXTLIBS += $(LIB_4_CRYPTO) BASIC_CFLAGS += -DSHA256_OPENSSL @@ -2151,6 +2196,10 @@ ifdef HAVE_NS_GET_EXECUTABLE_PATH BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH endif +ifdef HAVE_ZOS_GET_EXECUTABLE_PATH + BASIC_CFLAGS += -DHAVE_ZOS_GET_EXECUTABLE_PATH +endif + ifdef HAVE_WPGMPTR BASIC_CFLAGS += -DHAVE_WPGMPTR endif @@ -2373,9 +2422,12 @@ endif FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o FUZZ_OBJS += oss-fuzz/fuzz-config.o +FUZZ_OBJS += oss-fuzz/fuzz-credential-from-url-gently.o FUZZ_OBJS += oss-fuzz/fuzz-date.o FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o +FUZZ_OBJS += oss-fuzz/fuzz-parse-attr-line.o +FUZZ_OBJS += oss-fuzz/fuzz-url-decode-mem.o .PHONY: fuzz-objs fuzz-objs: $(FUZZ_OBJS) @@ -2668,25 +2720,15 @@ REFTABLE_OBJS += reftable/error.o REFTABLE_OBJS += reftable/block.o REFTABLE_OBJS += reftable/blocksource.o REFTABLE_OBJS += reftable/iter.o -REFTABLE_OBJS += reftable/publicbasics.o REFTABLE_OBJS += reftable/merged.o REFTABLE_OBJS += reftable/pq.o REFTABLE_OBJS += reftable/reader.o REFTABLE_OBJS += reftable/record.o -REFTABLE_OBJS += reftable/generic.o REFTABLE_OBJS += reftable/stack.o +REFTABLE_OBJS += reftable/system.o REFTABLE_OBJS += reftable/tree.o REFTABLE_OBJS += reftable/writer.o -REFTABLE_TEST_OBJS += reftable/block_test.o -REFTABLE_TEST_OBJS += reftable/dump.o -REFTABLE_TEST_OBJS += reftable/merged_test.o -REFTABLE_TEST_OBJS += reftable/pq_test.o -REFTABLE_TEST_OBJS += reftable/readwrite_test.o -REFTABLE_TEST_OBJS += reftable/stack_test.o -REFTABLE_TEST_OBJS += reftable/test_framework.o -REFTABLE_TEST_OBJS += reftable/tree_test.o - TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) .PHONY: test-objs @@ -2711,6 +2753,8 @@ OBJECTS += $(XDIFF_OBJS) OBJECTS += $(FUZZ_OBJS) OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) OBJECTS += $(UNIT_TEST_OBJS) +OBJECTS += $(CLAR_TEST_OBJS) +OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS)) ifndef NO_CURL OBJECTS += http.o http-walker.o remote-curl.o @@ -2861,9 +2905,6 @@ $(XDIFF_LIB): $(XDIFF_OBJS) $(REFTABLE_LIB): $(REFTABLE_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ -$(REFTABLE_TEST_LIB): $(REFTABLE_TEST_OBJS) - $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ - export DEFAULT_EDITOR DEFAULT_PAGER Documentation/GIT-EXCLUDED-PROGRAMS: FORCE @@ -3134,6 +3175,7 @@ GIT-BUILD-OPTIONS: FORCE @echo PYTHON_PATH=\''$(subst ','\'',$(PYTHON_PATH_SQ))'\' >>$@+ @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+ @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+ + @echo NO_ICONV=\''$(subst ','\'',$(subst ','\'',$(NO_ICONV)))'\' >>$@+ @echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+ @echo USE_LIBPCRE2=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE2)))'\' >>$@+ @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+ @@ -3213,7 +3255,7 @@ endif test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X)) -all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) +all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) bin-wrappers/%: wrap-for-bin.sh $(call mkdir_p_parent_template) @@ -3243,15 +3285,16 @@ perf: all t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) $(UNIT_TEST_DIR)/test-lib.o -t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(REFTABLE_TEST_LIB) +t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS) check-sha1:: t/helper/test-tool$X t/helper/test-sha1.sh -SP_OBJ = $(patsubst %.o,%.sp,$(OBJECTS)) +SP_SRC = $(filter-out $(THIRD_PARTY_SOURCES),$(patsubst %.o,%.c,$(OBJECTS))) +SP_OBJ = $(patsubst %.c,%.sp,$(SP_SRC)) -$(SP_OBJ): %.sp: %.c %.o +$(SP_OBJ): %.sp: %.c %.o $(GENERATED_H) $(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \ -Wsparse-error \ $(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $< && \ @@ -3260,7 +3303,7 @@ $(SP_OBJ): %.sp: %.c %.o .PHONY: sparse sparse: $(SP_OBJ) -EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% +EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% $(UNIT_TEST_DIR)/clar/% $(UNIT_TEST_DIR)/clar/clar/% ifndef OPENSSL_SHA1 EXCEPT_HDRS += sha1/openssl.h endif @@ -3281,7 +3324,7 @@ HCC = $(HCO:hco=hcc) @echo '#include "git-compat-util.h"' >$@ @echo '#include "$<"' >>$@ -$(HCO): %.hco: %.hcc FORCE +$(HCO): %.hco: %.hcc $(GENERATED_H) FORCE $(QUIET_HDR)$(CC) $(ALL_CFLAGS) -o /dev/null -c -xc $< .PHONY: hdr-check $(HCO) @@ -3292,7 +3335,7 @@ style: git clang-format --style file --diff --extensions c,h .PHONY: check -check: $(GENERATED_H) +check: @if sparse; \ then \ echo >&2 "Use 'make sparse' instead"; \ @@ -3644,7 +3687,7 @@ endif artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \ GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \ - $(UNIT_TEST_PROGS) $(MOFILES) + $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) $(MOFILES) $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \ SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)' test -n "$(ARTIFACTS_DIRECTORY)" @@ -3700,11 +3743,12 @@ cocciclean: clean: profile-clean coverage-clean cocciclean $(RM) -r .build $(UNIT_TEST_BIN) + $(RM) GIT-TEST-SUITES $(RM) po/git.pot po/git-core.pot $(RM) git.res $(RM) $(OBJECTS) $(RM) headless-git.o - $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB) + $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) $(RM) $(TEST_PROGRAMS) $(RM) $(FUZZ_PROGRAMS) @@ -3851,15 +3895,31 @@ $(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS -Wl,--allow-multiple-definition \ $(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE) -$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \ - $(UNIT_TEST_DIR)/test-lib.o \ - $(UNIT_TEST_DIR)/lib-oid.o \ +$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_OBJS) \ $(GITLIBS) GIT-LDFLAGS $(call mkdir_p_parent_template) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ $(filter %.o,$^) $(filter %.a,$^) $(LIBS) +GIT-TEST-SUITES: FORCE + @FLAGS='$(CLAR_TEST_SUITES)'; \ + if test x"$$FLAGS" != x"`cat GIT-TEST-SUITES 2>/dev/null`" ; then \ + echo >&2 " * new test suites"; \ + echo "$$FLAGS" >GIT-TEST-SUITES; \ + fi + +$(UNIT_TEST_DIR)/clar-decls.h: $(patsubst %,$(UNIT_TEST_DIR)/%.c,$(CLAR_TEST_SUITES)) $(UNIT_TEST_DIR)/generate-clar-decls.sh GIT-TEST-SUITES + $(QUIET_GEN)$(SHELL_PATH) $(UNIT_TEST_DIR)/generate-clar-decls.sh "$@" $(filter %.c,$^) +$(UNIT_TEST_DIR)/clar.suite: $(UNIT_TEST_DIR)/clar-decls.h $(UNIT_TEST_DIR)/generate-clar-suites.sh + $(QUIET_GEN)$(SHELL_PATH) $(UNIT_TEST_DIR)/generate-clar-suites.sh $< $(UNIT_TEST_DIR)/clar.suite +$(UNIT_TEST_DIR)/clar/clar.o: $(UNIT_TEST_DIR)/clar.suite +$(CLAR_TEST_OBJS): $(UNIT_TEST_DIR)/clar-decls.h +$(CLAR_TEST_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR) +$(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT-LDFLAGS + $(call mkdir_p_parent_template) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) + .PHONY: build-unit-tests unit-tests -build-unit-tests: $(UNIT_TEST_PROGS) -unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X +build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) +unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X $(MAKE) -C t/ unit-tests @@ -1 +1 @@ -Documentation/RelNotes/2.46.0.txt
\ No newline at end of file +Documentation/RelNotes/2.48.0.txt
\ No newline at end of file diff --git a/add-patch.c b/add-patch.c index 6e176cd21a..557903310d 100644 --- a/add-patch.c +++ b/add-patch.c @@ -7,9 +7,11 @@ #include "environment.h" #include "gettext.h" #include "object-name.h" +#include "pager.h" #include "read-cache-ll.h" #include "repository.h" #include "strbuf.h" +#include "sigchain.h" #include "run-command.h" #include "strvec.h" #include "pathspec.h" @@ -402,6 +404,12 @@ static void complete_file(char marker, struct hunk *hunk) hunk->splittable_into++; } +/* Empty context lines may omit the leading ' ' */ +static int normalize_marker(const char *p) +{ + return p[0] == '\n' || (p[0] == '\r' && p[1] == '\n') ? ' ' : p[0]; +} + static int parse_diff(struct add_p_state *s, const struct pathspec *ps) { struct strvec args = STRVEC_INIT; @@ -487,6 +495,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) while (p != pend) { char *eol = memchr(p, '\n', pend - p); const char *deleted = NULL, *mode_change = NULL; + char ch = normalize_marker(p); if (!eol) eol = pend; @@ -534,7 +543,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) * Start counting into how many hunks this one can be * split */ - marker = *p; + marker = ch; } else if (hunk == &file_diff->head && starts_with(p, "new file")) { file_diff->added = 1; @@ -588,10 +597,10 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) (int)(eol - (plain->buf + file_diff->head.start)), plain->buf + file_diff->head.start); - if ((marker == '-' || marker == '+') && *p == ' ') + if ((marker == '-' || marker == '+') && ch == ' ') hunk->splittable_into++; - if (marker && *p != '\\') - marker = *p; + if (marker && ch != '\\') + marker = ch; p = eol == pend ? pend : eol + 1; hunk->end = p - plain->buf; @@ -815,7 +824,7 @@ static int merge_hunks(struct add_p_state *s, struct file_diff *file_diff, (int)(hunk->end - hunk->start), plain + hunk->start); - if (plain[overlap_end] != ' ') + if (normalize_marker(&plain[overlap_end]) != ' ') return error(_("expected context line " "#%d in\n%.*s"), (int)(j + 1), @@ -955,7 +964,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, context_line_count = 0; while (splittable_into > 1) { - ch = s->plain.buf[current]; + ch = normalize_marker(&s->plain.buf[current]); if (!ch) BUG("buffer overrun while splitting hunks"); @@ -1133,7 +1142,8 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk) "removed, then the edit is\n" "aborted and the hunk is left unchanged.\n")); - if (strbuf_edit_interactively(&s->buf, "addp-hunk-edit.diff", NULL) < 0) + if (strbuf_edit_interactively(the_repository, &s->buf, + "addp-hunk-edit.diff", NULL) < 0) return -1; /* strip out commented lines */ @@ -1173,14 +1183,14 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, header->old_count = header->new_count = 0; for (i = hunk->start; i < hunk->end; ) { - switch (s->plain.buf[i]) { + switch(normalize_marker(&s->plain.buf[i])) { case '-': header->old_count++; break; case '+': header->new_count++; break; - case ' ': case '\r': case '\n': + case ' ': header->old_count++; header->new_count++; break; @@ -1391,7 +1401,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" - "p - print the current hunk\n" + "p - print the current hunk, 'P' to use the pager\n" "? - print help\n"); static int patch_update_file(struct add_p_state *s, @@ -1402,7 +1412,7 @@ static int patch_update_file(struct add_p_state *s, struct hunk *hunk; char ch; struct child_process cp = CHILD_PROCESS_INIT; - int colored = !!s->colored.len, quit = 0; + int colored = !!s->colored.len, quit = 0, use_pager = 0; enum prompt_mode_type prompt_mode_type; enum { ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0, @@ -1452,9 +1462,18 @@ static int patch_update_file(struct add_p_state *s, strbuf_reset(&s->buf); if (file_diff->hunk_nr) { if (rendered_hunk_index != hunk_index) { + if (use_pager) { + setup_pager(); + sigchain_push(SIGPIPE, SIG_IGN); + } render_hunk(s, hunk, 0, colored, &s->buf); fputs(s->buf.buf, stdout); rendered_hunk_index = hunk_index; + if (use_pager) { + sigchain_pop(SIGPIPE); + wait_for_pager(); + use_pager = 0; + } } strbuf_reset(&s->buf); @@ -1675,8 +1694,9 @@ soft_increment: hunk->use = USE_HUNK; goto soft_increment; } - } else if (s->answer.buf[0] == 'p') { + } else if (ch == 'p') { rendered_hunk_index = -1; + use_pager = (s->answer.buf[0] == 'P') ? 1 : 0; } else if (s->answer.buf[0] == '?') { const char *p = _(help_patch_remainder), *eol = p; @@ -93,7 +93,7 @@ static struct { static const char turn_off_instructions[] = N_("\n" - "Disable this message with \"git config advice.%s false\""); + "Disable this message with \"git config set advice.%s false\""); static void vadvise(const char *advice, int display_instructions, const char *key, va_list params) @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "alias.h" #include "config.h" @@ -37,7 +39,7 @@ char *alias_lookup(const char *alias) { struct config_alias_data data = { alias, NULL }; - read_early_config(config_alias_cb, &data); + read_early_config(the_repository, config_alias_cb, &data); return data.v; } @@ -46,7 +48,7 @@ void list_aliases(struct string_list *list) { struct config_alias_data data = { NULL, NULL, list }; - read_early_config(config_alias_cb, &data); + read_early_config(the_repository, config_alias_cb, &data); } void quote_cmdline(struct strbuf *buf, const char **argv) @@ -30,6 +30,7 @@ #include "path.h" #include "quote.h" #include "read-cache.h" +#include "repository.h" #include "rerere.h" #include "apply.h" #include "entry.h" @@ -277,13 +278,26 @@ struct line { * This represents a "file", which is an array of "lines". */ struct image { - char *buf; - size_t len; - size_t nr; - size_t alloc; - struct line *line_allocated; + struct strbuf buf; struct line *line; + size_t line_nr, line_alloc; }; +#define IMAGE_INIT { \ + .buf = STRBUF_INIT, \ +} + +static void image_init(struct image *image) +{ + struct image empty = IMAGE_INIT; + memcpy(image, &empty, sizeof(*image)); +} + +static void image_clear(struct image *image) +{ + strbuf_release(&image->buf); + free(image->line); + image_init(image); +} static uint32_t hash_line(const char *cp, size_t len) { @@ -297,49 +311,13 @@ static uint32_t hash_line(const char *cp, size_t len) return h; } -/* - * Compare lines s1 of length n1 and s2 of length n2, ignoring - * whitespace difference. Returns 1 if they match, 0 otherwise - */ -static int fuzzy_matchlines(const char *s1, size_t n1, - const char *s2, size_t n2) -{ - const char *end1 = s1 + n1; - const char *end2 = s2 + n2; - - /* ignore line endings */ - while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n')) - end1--; - while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n')) - end2--; - - while (s1 < end1 && s2 < end2) { - if (isspace(*s1)) { - /* - * Skip whitespace. We check on both buffers - * because we don't want "a b" to match "ab". - */ - if (!isspace(*s2)) - return 0; - while (s1 < end1 && isspace(*s1)) - s1++; - while (s2 < end2 && isspace(*s2)) - s2++; - } else if (*s1++ != *s2++) - return 0; - } - - /* If we reached the end on one side only, lines don't match. */ - return s1 == end1 && s2 == end2; -} - -static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag) +static void image_add_line(struct image *img, const char *bol, size_t len, unsigned flag) { - ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc); - img->line_allocated[img->nr].len = len; - img->line_allocated[img->nr].hash = hash_line(bol, len); - img->line_allocated[img->nr].flag = flag; - img->nr++; + ALLOC_GROW(img->line, img->line_nr + 1, img->line_alloc); + img->line[img->line_nr].len = len; + img->line[img->line_nr].hash = hash_line(bol, len); + img->line[img->line_nr].flag = flag; + img->line_nr++; } /* @@ -347,37 +325,43 @@ static void add_line_info(struct image *img, const char *bol, size_t len, unsign * attach it to "image" and add line-based index to it. * "image" now owns the "buf". */ -static void prepare_image(struct image *image, char *buf, size_t len, +static void image_prepare(struct image *image, char *buf, size_t len, int prepare_linetable) { const char *cp, *ep; - memset(image, 0, sizeof(*image)); - image->buf = buf; - image->len = len; + image_clear(image); + strbuf_attach(&image->buf, buf, len, len + 1); if (!prepare_linetable) return; - ep = image->buf + image->len; - cp = image->buf; + ep = image->buf.buf + image->buf.len; + cp = image->buf.buf; while (cp < ep) { const char *next; for (next = cp; next < ep && *next != '\n'; next++) ; if (next < ep) next++; - add_line_info(image, cp, next - cp, 0); + image_add_line(image, cp, next - cp, 0); cp = next; } - image->line = image->line_allocated; } -static void clear_image(struct image *image) +static void image_remove_first_line(struct image *img) +{ + strbuf_remove(&img->buf, 0, img->line[0].len); + img->line_nr--; + if (img->line_nr) + MOVE_ARRAY(img->line, img->line + 1, img->line_nr); +} + +static void image_remove_last_line(struct image *img) { - free(image->buf); - free(image->line_allocated); - memset(image, 0, sizeof(*image)); + size_t last_line_len = img->line[img->line_nr - 1].len; + strbuf_setlen(&img->buf, img->buf.len - last_line_len); + img->line_nr--; } /* fmt must contain _one_ %s and no other substitution */ @@ -995,6 +979,7 @@ static int parse_mode_line(const char *line, int linenr, unsigned int *mode) *mode = strtoul(line, &end, 8); if (end == line || !isspace(*end)) return error(_("invalid mode on line %d: %s"), linenr, line); + *mode = canon_mode(*mode); return 0; } @@ -2325,65 +2310,43 @@ static int read_old_data(struct stat *st, struct patch *patch, /* * Update the preimage, and the common lines in postimage, - * from buffer buf of length len. If postlen is 0 the postimage - * is updated in place, otherwise it's updated on a new buffer - * of length postlen + * from buffer buf of length len. */ - static void update_pre_post_images(struct image *preimage, struct image *postimage, - char *buf, - size_t len, size_t postlen) + char *buf, size_t len) { + struct image fixed_preimage = IMAGE_INIT; + size_t insert_pos = 0; int i, ctx, reduced; - char *new_buf, *old_buf, *fixed; - struct image fixed_preimage; + const char *fixed; /* * Update the preimage with whitespace fixes. Note that we * are not losing preimage->buf -- apply_one_fragment() will * free "oldlines". */ - prepare_image(&fixed_preimage, buf, len, 1); - assert(postlen - ? fixed_preimage.nr == preimage->nr - : fixed_preimage.nr <= preimage->nr); - for (i = 0; i < fixed_preimage.nr; i++) + image_prepare(&fixed_preimage, buf, len, 1); + for (i = 0; i < fixed_preimage.line_nr; i++) fixed_preimage.line[i].flag = preimage->line[i].flag; - free(preimage->line_allocated); + image_clear(preimage); *preimage = fixed_preimage; + fixed = preimage->buf.buf; /* - * Adjust the common context lines in postimage. This can be - * done in-place when we are shrinking it with whitespace - * fixing, but needs a new buffer when ignoring whitespace or - * expanding leading tabs to spaces. - * - * We trust the caller to tell us if the update can be done - * in place (postlen==0) or not. + * Adjust the common context lines in postimage. */ - old_buf = postimage->buf; - if (postlen) - new_buf = postimage->buf = xmalloc(postlen); - else - new_buf = old_buf; - fixed = preimage->buf; - - for (i = reduced = ctx = 0; i < postimage->nr; i++) { + for (i = reduced = ctx = 0; i < postimage->line_nr; i++) { size_t l_len = postimage->line[i].len; + if (!(postimage->line[i].flag & LINE_COMMON)) { /* an added line -- no counterparts in preimage */ - memmove(new_buf, old_buf, l_len); - old_buf += l_len; - new_buf += l_len; + insert_pos += l_len; continue; } - /* a common context -- skip it in the original postimage */ - old_buf += l_len; - /* and find the corresponding one in the fixed preimage */ - while (ctx < preimage->nr && + while (ctx < preimage->line_nr && !(preimage->line[ctx].flag & LINE_COMMON)) { fixed += preimage->line[ctx].len; ctx++; @@ -2393,29 +2356,59 @@ static void update_pre_post_images(struct image *preimage, * preimage is expected to run out, if the caller * fixed addition of trailing blank lines. */ - if (preimage->nr <= ctx) { + if (preimage->line_nr <= ctx) { reduced++; continue; } /* and copy it in, while fixing the line length */ l_len = preimage->line[ctx].len; - memcpy(new_buf, fixed, l_len); - new_buf += l_len; + strbuf_splice(&postimage->buf, insert_pos, postimage->line[i].len, + fixed, l_len); + insert_pos += l_len; fixed += l_len; postimage->line[i].len = l_len; ctx++; } - if (postlen - ? postlen < new_buf - postimage->buf - : postimage->len < new_buf - postimage->buf) - BUG("caller miscounted postlen: asked %d, orig = %d, used = %d", - (int)postlen, (int) postimage->len, (int)(new_buf - postimage->buf)); - /* Fix the length of the whole thing */ - postimage->len = new_buf - postimage->buf; - postimage->nr -= reduced; + postimage->line_nr -= reduced; +} + +/* + * Compare lines s1 of length n1 and s2 of length n2, ignoring + * whitespace difference. Returns 1 if they match, 0 otherwise + */ +static int fuzzy_matchlines(const char *s1, size_t n1, + const char *s2, size_t n2) +{ + const char *end1 = s1 + n1; + const char *end2 = s2 + n2; + + /* ignore line endings */ + while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n')) + end1--; + while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n')) + end2--; + + while (s1 < end1 && s2 < end2) { + if (isspace(*s1)) { + /* + * Skip whitespace. We check on both buffers + * because we don't want "a b" to match "ab". + */ + if (!isspace(*s2)) + return 0; + while (s1 < end1 && isspace(*s1)) + s1++; + while (s2 < end2 && isspace(*s2)) + s2++; + } else if (*s1++ != *s2++) + return 0; + } + + /* If we reached the end on one side only, lines don't match. */ + return s1 == end1 && s2 == end2; } static int line_by_line_fuzzy_match(struct image *img, @@ -2428,7 +2421,6 @@ static int line_by_line_fuzzy_match(struct image *img, int i; size_t imgoff = 0; size_t preoff = 0; - size_t postlen = postimage->len; size_t extra_chars; char *buf; char *preimage_eof; @@ -2441,11 +2433,9 @@ static int line_by_line_fuzzy_match(struct image *img, size_t prelen = preimage->line[i].len; size_t imglen = img->line[current_lno+i].len; - if (!fuzzy_matchlines(img->buf + current + imgoff, imglen, - preimage->buf + preoff, prelen)) + if (!fuzzy_matchlines(img->buf.buf + current + imgoff, imglen, + preimage->buf.buf + preoff, prelen)) return 0; - if (preimage->line[i].flag & LINE_COMMON) - postlen += imglen - prelen; imgoff += imglen; preoff += prelen; } @@ -2461,10 +2451,10 @@ static int line_by_line_fuzzy_match(struct image *img, * are whitespace characters. (This can only happen if * we are removing blank lines at the end of the file.) */ - buf = preimage_eof = preimage->buf + preoff; - for ( ; i < preimage->nr; i++) + buf = preimage_eof = preimage->buf.buf + preoff; + for ( ; i < preimage->line_nr; i++) preoff += preimage->line[i].len; - preimage_end = preimage->buf + preoff; + preimage_end = preimage->buf.buf + preoff; for ( ; buf < preimage_end; buf++) if (!isspace(*buf)) return 0; @@ -2478,11 +2468,11 @@ static int line_by_line_fuzzy_match(struct image *img, */ extra_chars = preimage_end - preimage_eof; strbuf_init(&fixed, imgoff + extra_chars); - strbuf_add(&fixed, img->buf + current, imgoff); + strbuf_add(&fixed, img->buf.buf + current, imgoff); strbuf_add(&fixed, preimage_eof, extra_chars); fixed_buf = strbuf_detach(&fixed, &fixed_len); update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, postlen); + fixed_buf, fixed_len); return 1; } @@ -2498,16 +2488,17 @@ static int match_fragment(struct apply_state *state, int i; const char *orig, *target; struct strbuf fixed = STRBUF_INIT; - size_t postlen; + char *fixed_buf; + size_t fixed_len; int preimage_limit; int ret; - if (preimage->nr + current_lno <= img->nr) { + if (preimage->line_nr + current_lno <= img->line_nr) { /* * The hunk falls within the boundaries of img. */ - preimage_limit = preimage->nr; - if (match_end && (preimage->nr + current_lno != img->nr)) { + preimage_limit = preimage->line_nr; + if (match_end && (preimage->line_nr + current_lno != img->line_nr)) { ret = 0; goto out; } @@ -2520,7 +2511,7 @@ static int match_fragment(struct apply_state *state, * match with img, and the remainder of the preimage * must be blank. */ - preimage_limit = img->nr - current_lno; + preimage_limit = img->line_nr - current_lno; } else { /* * The hunk extends beyond the end of the img and @@ -2545,7 +2536,7 @@ static int match_fragment(struct apply_state *state, } } - if (preimage_limit == preimage->nr) { + if (preimage_limit == preimage->line_nr) { /* * Do we have an exact match? If we were told to match * at the end, size must be exactly at current+fragsize, @@ -2554,9 +2545,9 @@ static int match_fragment(struct apply_state *state, * exactly. */ if ((match_end - ? (current + preimage->len == img->len) - : (current + preimage->len <= img->len)) && - !memcmp(img->buf + current, preimage->buf, preimage->len)) { + ? (current + preimage->buf.len == img->buf.len) + : (current + preimage->buf.len <= img->buf.len)) && + !memcmp(img->buf.buf + current, preimage->buf.buf, preimage->buf.len)) { ret = 1; goto out; } @@ -2570,7 +2561,7 @@ static int match_fragment(struct apply_state *state, */ const char *buf, *buf_end; - buf = preimage->buf; + buf = preimage->buf.buf; buf_end = buf; for (i = 0; i < preimage_limit; i++) buf_end += preimage->line[i].len; @@ -2615,21 +2606,14 @@ static int match_fragment(struct apply_state *state, * fixed. */ - /* First count added lines in postimage */ - postlen = 0; - for (i = 0; i < postimage->nr; i++) { - if (!(postimage->line[i].flag & LINE_COMMON)) - postlen += postimage->line[i].len; - } - /* * The preimage may extend beyond the end of the file, * but in this loop we will only handle the part of the * preimage that falls within the file. */ - strbuf_grow(&fixed, preimage->len + 1); - orig = preimage->buf; - target = img->buf + current; + strbuf_grow(&fixed, preimage->buf.len + 1); + orig = preimage->buf.buf; + target = img->buf.buf + current; for (i = 0; i < preimage_limit; i++) { size_t oldlen = preimage->line[i].len; size_t tgtlen = img->line[current_lno + i].len; @@ -2658,10 +2642,6 @@ static int match_fragment(struct apply_state *state, !memcmp(tgtfix.buf, fixed.buf + fixstart, fixed.len - fixstart)); - /* Add the length if this is common with the postimage */ - if (preimage->line[i].flag & LINE_COMMON) - postlen += tgtfix.len; - strbuf_release(&tgtfix); if (!match) { ret = 0; @@ -2679,7 +2659,7 @@ static int match_fragment(struct apply_state *state, * empty or only contain whitespace (if WS_BLANK_AT_EOL is * false). */ - for ( ; i < preimage->nr; i++) { + for ( ; i < preimage->line_nr; i++) { size_t fixstart = fixed.len; /* start of the fixed preimage */ size_t oldlen = preimage->line[i].len; int j; @@ -2703,10 +2683,9 @@ static int match_fragment(struct apply_state *state, * has whitespace breakages unfixed, and fixing them makes the * hunk match. Update the context lines in the postimage. */ - if (postlen < postimage->len) - postlen = 0; + fixed_buf = strbuf_detach(&fixed, &fixed_len); update_pre_post_images(preimage, postimage, - fixed.buf, fixed.len, postlen); + fixed_buf, fixed_len); ret = 1; @@ -2734,7 +2713,7 @@ static int find_pos(struct apply_state *state, * than `match_beginning`. */ if (state->allow_overlap && match_beginning && match_end && - img->nr - preimage->nr != 0) + img->line_nr - preimage->line_nr != 0) match_beginning = 0; /* @@ -2745,15 +2724,15 @@ static int find_pos(struct apply_state *state, if (match_beginning) line = 0; else if (match_end) - line = img->nr - preimage->nr; + line = img->line_nr - preimage->line_nr; /* * Because the comparison is unsigned, the following test * will also take care of a negative line number that can * result when match_end and preimage is larger than the target. */ - if ((size_t) line > img->nr) - line = img->nr; + if ((size_t) line > img->line_nr) + line = img->line_nr; current = 0; for (i = 0; i < line; i++) @@ -2776,7 +2755,7 @@ static int find_pos(struct apply_state *state, return current_lno; again: - if (backwards_lno == 0 && forwards_lno == img->nr) + if (backwards_lno == 0 && forwards_lno == img->line_nr) break; if (i & 1) { @@ -2789,7 +2768,7 @@ static int find_pos(struct apply_state *state, current = backwards; current_lno = backwards_lno; } else { - if (forwards_lno == img->nr) { + if (forwards_lno == img->line_nr) { i++; goto again; } @@ -2803,19 +2782,6 @@ static int find_pos(struct apply_state *state, return -1; } -static void remove_first_line(struct image *img) -{ - img->buf += img->line[0].len; - img->len -= img->line[0].len; - img->line++; - img->nr--; -} - -static void remove_last_line(struct image *img) -{ - img->len -= img->line[--img->nr].len; -} - /* * The change from "preimage" and "postimage" has been found to * apply at applied_pos (counts in line numbers) in "img". @@ -2833,6 +2799,7 @@ static void update_image(struct apply_state *state, */ int i, nr; size_t remove_count, insert_count, applied_at = 0; + size_t result_alloc; char *result; int preimage_limit; @@ -2845,9 +2812,9 @@ static void update_image(struct apply_state *state, * to the number of lines in the preimage that falls * within the boundaries. */ - preimage_limit = preimage->nr; - if (preimage_limit > img->nr - applied_pos) - preimage_limit = img->nr - applied_pos; + preimage_limit = preimage->line_nr; + if (preimage_limit > img->line_nr - applied_pos) + preimage_limit = img->line_nr - applied_pos; for (i = 0; i < applied_pos; i++) applied_at += img->line[i].len; @@ -2855,39 +2822,36 @@ static void update_image(struct apply_state *state, remove_count = 0; for (i = 0; i < preimage_limit; i++) remove_count += img->line[applied_pos + i].len; - insert_count = postimage->len; + insert_count = postimage->buf.len; /* Adjust the contents */ - result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1)); - memcpy(result, img->buf, applied_at); - memcpy(result + applied_at, postimage->buf, postimage->len); - memcpy(result + applied_at + postimage->len, - img->buf + (applied_at + remove_count), - img->len - (applied_at + remove_count)); - free(img->buf); - img->buf = result; - img->len += insert_count - remove_count; - result[img->len] = '\0'; + result_alloc = st_add3(st_sub(img->buf.len, remove_count), insert_count, 1); + result = xmalloc(result_alloc); + memcpy(result, img->buf.buf, applied_at); + memcpy(result + applied_at, postimage->buf.buf, postimage->buf.len); + memcpy(result + applied_at + postimage->buf.len, + img->buf.buf + (applied_at + remove_count), + img->buf.len - (applied_at + remove_count)); + strbuf_attach(&img->buf, result, postimage->buf.len + img->buf.len - remove_count, + result_alloc); /* Adjust the line table */ - nr = img->nr + postimage->nr - preimage_limit; - if (preimage_limit < postimage->nr) { + nr = img->line_nr + postimage->line_nr - preimage_limit; + if (preimage_limit < postimage->line_nr) /* - * NOTE: this knows that we never call remove_first_line() + * NOTE: this knows that we never call image_remove_first_line() * on anything other than pre/post image. */ REALLOC_ARRAY(img->line, nr); - img->line_allocated = img->line; - } - if (preimage_limit != postimage->nr) - MOVE_ARRAY(img->line + applied_pos + postimage->nr, + if (preimage_limit != postimage->line_nr) + MOVE_ARRAY(img->line + applied_pos + postimage->line_nr, img->line + applied_pos + preimage_limit, - img->nr - (applied_pos + preimage_limit)); - COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->nr); + img->line_nr - (applied_pos + preimage_limit)); + COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->line_nr); if (!state->allow_overlap) - for (i = 0; i < postimage->nr; i++) + for (i = 0; i < postimage->line_nr; i++) img->line[applied_pos + i].flag |= LINE_PATCHED; - img->nr = nr; + img->line_nr = nr; } /* @@ -2910,11 +2874,9 @@ static int apply_one_fragment(struct apply_state *state, int hunk_linenr = frag->linenr; unsigned long leading, trailing; int pos, applied_pos; - struct image preimage; - struct image postimage; + struct image preimage = IMAGE_INIT; + struct image postimage = IMAGE_INIT; - memset(&preimage, 0, sizeof(preimage)); - memset(&postimage, 0, sizeof(postimage)); oldlines = xmalloc(size); strbuf_init(&newlines, size); @@ -2956,8 +2918,8 @@ static int apply_one_fragment(struct apply_state *state, break; *old++ = '\n'; strbuf_addch(&newlines, '\n'); - add_line_info(&preimage, "\n", 1, LINE_COMMON); - add_line_info(&postimage, "\n", 1, LINE_COMMON); + image_add_line(&preimage, "\n", 1, LINE_COMMON); + image_add_line(&postimage, "\n", 1, LINE_COMMON); is_blank_context = 1; break; case ' ': @@ -2967,7 +2929,7 @@ static int apply_one_fragment(struct apply_state *state, /* fallthrough */ case '-': memcpy(old, patch + 1, plen); - add_line_info(&preimage, old, plen, + image_add_line(&preimage, old, plen, (first == ' ' ? LINE_COMMON : 0)); old += plen; if (first == '-') @@ -2987,7 +2949,7 @@ static int apply_one_fragment(struct apply_state *state, else { ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws); } - add_line_info(&postimage, newlines.buf + start, newlines.len - start, + image_add_line(&postimage, newlines.buf + start, newlines.len - start, (first == '+' ? 0 : LINE_COMMON)); if (first == '+' && (ws_rule & WS_BLANK_AT_EOF) && @@ -3021,8 +2983,8 @@ static int apply_one_fragment(struct apply_state *state, newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') { old--; strbuf_setlen(&newlines, newlines.len - 1); - preimage.line_allocated[preimage.nr - 1].len--; - postimage.line_allocated[postimage.nr - 1].len--; + preimage.line[preimage.line_nr - 1].len--; + postimage.line[postimage.line_nr - 1].len--; } leading = frag->leading; @@ -3052,12 +3014,8 @@ static int apply_one_fragment(struct apply_state *state, match_end = !state->unidiff_zero && !trailing; pos = frag->newpos ? (frag->newpos - 1) : 0; - preimage.buf = oldlines; - preimage.len = old - oldlines; - postimage.buf = newlines.buf; - postimage.len = newlines.len; - preimage.line = preimage.line_allocated; - postimage.line = postimage.line_allocated; + strbuf_add(&preimage.buf, oldlines, old - oldlines); + strbuf_swap(&postimage.buf, &newlines); for (;;) { @@ -3081,28 +3039,28 @@ static int apply_one_fragment(struct apply_state *state, * just reduce the larger context. */ if (leading >= trailing) { - remove_first_line(&preimage); - remove_first_line(&postimage); + image_remove_first_line(&preimage); + image_remove_first_line(&postimage); pos--; leading--; } if (trailing > leading) { - remove_last_line(&preimage); - remove_last_line(&postimage); + image_remove_last_line(&preimage); + image_remove_last_line(&postimage); trailing--; } } if (applied_pos >= 0) { if (new_blank_lines_at_end && - preimage.nr + applied_pos >= img->nr && + preimage.line_nr + applied_pos >= img->line_nr && (ws_rule & WS_BLANK_AT_EOF) && state->ws_error_action != nowarn_ws_error) { record_ws_error(state, WS_BLANK_AT_EOF, "+", 1, found_new_blank_lines_at_end); if (state->ws_error_action == correct_ws_error) { while (new_blank_lines_at_end--) - remove_last_line(&postimage); + image_remove_last_line(&postimage); } /* * We would want to prevent write_out_results() @@ -3145,8 +3103,8 @@ static int apply_one_fragment(struct apply_state *state, out: free(oldlines); strbuf_release(&newlines); - free(preimage.line_allocated); - free(postimage.line_allocated); + image_clear(&preimage); + image_clear(&postimage); return (applied_pos < 0); } @@ -3176,18 +3134,16 @@ static int apply_binary_fragment(struct apply_state *state, } switch (fragment->binary_patch_method) { case BINARY_DELTA_DEFLATED: - dst = patch_delta(img->buf, img->len, fragment->patch, + dst = patch_delta(img->buf.buf, img->buf.len, fragment->patch, fragment->size, &len); if (!dst) return -1; - clear_image(img); - img->buf = dst; - img->len = len; + image_clear(img); + strbuf_attach(&img->buf, dst, len, len + 1); return 0; case BINARY_LITERAL_DEFLATED: - clear_image(img); - img->len = fragment->size; - img->buf = xmemdupz(fragment->patch, img->len); + image_clear(img); + strbuf_add(&img->buf, fragment->patch, fragment->size); return 0; } return -1; @@ -3223,8 +3179,8 @@ static int apply_binary(struct apply_state *state, * See if the old one matches what the patch * applies to. */ - hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB, - &oid); + hash_object_file(the_hash_algo, img->buf.buf, img->buf.len, + OBJ_BLOB, &oid); if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix)) return error(_("the patch applies to '%s' (%s), " "which does not match the " @@ -3233,14 +3189,14 @@ static int apply_binary(struct apply_state *state, } else { /* Otherwise, the old one must be empty. */ - if (img->len) + if (img->buf.len) return error(_("the patch applies to an empty " "'%s' but it is not empty"), name); } get_oid_hex(patch->new_oid_prefix, &oid); if (is_null_oid(&oid)) { - clear_image(img); + image_clear(img); return 0; /* deletion patch */ } @@ -3256,9 +3212,8 @@ static int apply_binary(struct apply_state *state, return error(_("the necessary postimage %s for " "'%s' cannot be read"), patch->new_oid_prefix, name); - clear_image(img); - img->buf = result; - img->len = size; + image_clear(img); + strbuf_attach(&img->buf, result, size, size + 1); } else { /* * We have verified buf matches the preimage; @@ -3270,7 +3225,7 @@ static int apply_binary(struct apply_state *state, name); /* verify that the result matches */ - hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB, + hash_object_file(the_hash_algo, img->buf.buf, img->buf.len, OBJ_BLOB, &oid); if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix)) return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"), @@ -3532,7 +3487,7 @@ static int load_preimage(struct apply_state *state, } img = strbuf_detach(&buf, &len); - prepare_image(image, img, len, !patch->is_binary); + image_prepare(image, img, len, !patch->is_binary); return 0; } @@ -3540,14 +3495,14 @@ static int resolve_to(struct image *image, const struct object_id *result_id) { unsigned long size; enum object_type type; + char *data; - clear_image(image); + image_clear(image); - image->buf = repo_read_object_file(the_repository, result_id, &type, - &size); - if (!image->buf || type != OBJ_BLOB) + data = repo_read_object_file(the_repository, result_id, &type, &size); + if (!data || type != OBJ_BLOB) die("unable to read blob object %s", oid_to_hex(result_id)); - image->len = size; + strbuf_attach(&image->buf, data, size, size + 1); return 0; } @@ -3560,6 +3515,7 @@ static int three_way_merge(struct apply_state *state, const struct object_id *theirs) { mmfile_t base_file, our_file, their_file; + struct ll_merge_options merge_opts = LL_MERGE_OPTIONS_INIT; mmbuffer_t result = { NULL }; enum ll_merge_result status; @@ -3572,12 +3528,13 @@ static int three_way_merge(struct apply_state *state, read_mmblob(&base_file, base); read_mmblob(&our_file, ours); read_mmblob(&their_file, theirs); + merge_opts.variant = state->merge_variant; status = ll_merge(&result, path, &base_file, "base", &our_file, "ours", &their_file, "theirs", state->repo->index, - NULL); + &merge_opts); if (status == LL_MERGE_BINARY_CONFLICT) warning("Cannot merge binary files: %s (%s vs. %s)", path, "ours", "theirs"); @@ -3588,9 +3545,8 @@ static int three_way_merge(struct apply_state *state, free(result.ptr); return -1; } - clear_image(image); - image->buf = result.ptr; - image->len = result.size; + image_clear(image); + strbuf_attach(&image->buf, result.ptr, result.size, result.size); return status; } @@ -3635,7 +3591,7 @@ static int load_current(struct apply_state *state, else if (status) return -1; img = strbuf_detach(&buf, &len); - prepare_image(image, img, len, !patch->is_binary); + image_prepare(image, img, len, !patch->is_binary); return 0; } @@ -3650,7 +3606,7 @@ static int try_threeway(struct apply_state *state, size_t len; int status; char *img; - struct image tmp_image; + struct image tmp_image = IMAGE_INIT; /* No point falling back to 3-way merge in these cases */ if (patch->is_delete || @@ -3670,15 +3626,15 @@ static int try_threeway(struct apply_state *state, fprintf(stderr, _("Performing three-way merge...\n")); img = strbuf_detach(&buf, &len); - prepare_image(&tmp_image, img, len, 1); + image_prepare(&tmp_image, img, len, 1); /* Apply the patch to get the post image */ if (apply_fragments(state, &tmp_image, patch) < 0) { - clear_image(&tmp_image); + image_clear(&tmp_image); return -1; } /* post_oid is theirs */ - write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid); - clear_image(&tmp_image); + write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid); + image_clear(&tmp_image); /* our_oid is ours */ if (patch->is_new) { @@ -3690,8 +3646,8 @@ static int try_threeway(struct apply_state *state, return error(_("cannot read the current contents of '%s'"), patch->old_name); } - write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid); - clear_image(&tmp_image); + write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid); + image_clear(&tmp_image); /* in-core three-way merge between post and our using pre as base */ status = three_way_merge(state, image, patch->new_name, @@ -3727,7 +3683,7 @@ static int try_threeway(struct apply_state *state, static int apply_data(struct apply_state *state, struct patch *patch, struct stat *st, const struct cache_entry *ce) { - struct image image; + struct image image = IMAGE_INIT; if (load_preimage(state, &image, patch, st, ce) < 0) return -1; @@ -3739,14 +3695,13 @@ static int apply_data(struct apply_state *state, struct patch *patch, /* Note: with --reject, apply_fragments() returns 0 */ if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) { - clear_image(&image); + image_clear(&image); return -1; } } - patch->result = image.buf; - patch->resultsize = image.len; + patch->result = strbuf_detach(&image.buf, &patch->resultsize); add_to_fn_table(state, patch); - free(image.line_allocated); + free(image.line); if (0 < patch->is_delete && patch->resultsize) return error(_("removal patch leaves file contents")); @@ -4110,7 +4065,7 @@ static int read_apply_cache(struct apply_state *state) { if (state->index_file) return read_index_from(state->repo->index, state->index_file, - get_git_dir()); + repo_get_git_dir(the_repository)); else return repo_read_index(state->repo); } @@ -5150,6 +5105,15 @@ int apply_parse_options(int argc, const char **argv, N_("also apply the patch (use with --stat/--summary/--check)")), OPT_BOOL('3', "3way", &state->threeway, N_( "attempt three-way merge, fall back on normal patch if that fails")), + OPT_SET_INT_F(0, "ours", &state->merge_variant, + N_("for conflicts, use our version"), + XDL_MERGE_FAVOR_OURS, PARSE_OPT_NONEG), + OPT_SET_INT_F(0, "theirs", &state->merge_variant, + N_("for conflicts, use their version"), + XDL_MERGE_FAVOR_THEIRS, PARSE_OPT_NONEG), + OPT_SET_INT_F(0, "union", &state->merge_variant, + N_("for conflicts, use a union version"), + XDL_MERGE_FAVOR_UNION, PARSE_OPT_NONEG), OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor, N_("build a temporary index based on embedded index information")), /* Think twice before adding "--nul" synonym to this */ @@ -5189,5 +5153,10 @@ int apply_parse_options(int argc, const char **argv, OPT_END() }; - return parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0); + argc = parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0); + + if (state->merge_variant && !state->threeway) + die(_("--ours, --theirs, and --union require --3way")); + + return argc; } @@ -59,6 +59,7 @@ struct apply_state { struct repository *repo; const char *index_file; enum apply_verbosity apply_verbosity; + int merge_variant; char *fake_ancestor; const char *patch_input_file; int line_termination; @@ -304,8 +304,6 @@ int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry) { struct archiver_context context; - struct unpack_trees_options opts; - struct tree_desc t; int err; struct strbuf path_in_archive = STRBUF_INIT; struct strbuf content = STRBUF_INIT; @@ -331,23 +329,6 @@ int write_archive_entries(struct archiver_args *args, context.args = args; context.write_entry = write_entry; - /* - * Setup index and instruct attr to read index only - */ - if (!args->worktree_attributes) { - memset(&opts, 0, sizeof(opts)); - opts.index_only = 1; - opts.head_idx = -1; - opts.src_index = args->repo->index; - opts.dst_index = args->repo->index; - opts.fn = oneway_merge; - init_tree_desc(&t, &args->tree->object.oid, - args->tree->buffer, args->tree->size); - if (unpack_trees(1, &t, &opts)) - return -1; - git_attr_set_direction(GIT_ATTR_INDEX); - } - err = read_tree(args->repo, args->tree, &args->pathspec, queue_or_write_archive_entry, @@ -540,6 +521,27 @@ static void parse_treeish_arg(const char **argv, if (!tree) die(_("not a tree object: %s"), oid_to_hex(&oid)); + /* + * Setup index and instruct attr to read index only + */ + if (!ar_args->worktree_attributes) { + struct unpack_trees_options opts; + struct tree_desc t; + + memset(&opts, 0, sizeof(opts)); + opts.index_only = 1; + opts.head_idx = -1; + opts.src_index = ar_args->repo->index; + opts.dst_index = ar_args->repo->index; + opts.fn = oneway_merge; + init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size); + if (unpack_trees(1, &t, &opts)) + die(_("failed to unpack tree object %s"), + oid_to_hex(&tree->object.oid)); + + git_attr_set_direction(GIT_ATTR_INDEX); + } + ar_args->refname = ref; ar_args->tree = tree; ar_args->commit_oid = commit_oid; @@ -736,6 +738,7 @@ int write_archive(int argc, const char **argv, const char *prefix, struct pretty_print_describe_status describe_status = {0}; struct pretty_print_context ctx = {0}; struct archiver_args args; + const char **argv_copy; int rc; git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable); @@ -749,6 +752,14 @@ int write_archive(int argc, const char **argv, const char *prefix, args.repo = repo; args.prefix = prefix; string_list_init_dup(&args.extra_files); + + /* + * `parse_archive_args()` modifies contents of `argv`, which is what we + * want. Our callers may not want it though, so we create a copy here. + */ + DUP_ARRAY(argv_copy, argv, argc); + argv = argv_copy; + argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote); if (!startup_info->have_repository) { /* @@ -767,6 +778,7 @@ int write_archive(int argc, const char **argv, const char *prefix, string_list_clear_func(&args.extra_files, extra_file_info_clear); free(args.refname); clear_pathspec(&args.pathspec); + free(argv_copy); return rc; } @@ -187,7 +187,7 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check) } /* - * Atribute name cannot begin with "builtin_" which + * Attribute name cannot begin with "builtin_" which * is a reserved namespace for built in attributes values. */ static int attr_name_reserved(const char *name) @@ -259,42 +259,6 @@ const struct git_attr *git_attr(const char *name) return git_attr_internal(name, strlen(name)); } -/* What does a matched pattern decide? */ -struct attr_state { - const struct git_attr *attr; - const char *setto; -}; - -struct pattern { - const char *pattern; - int patternlen; - int nowildcardlen; - unsigned flags; /* PATTERN_FLAG_* */ -}; - -/* - * One rule, as from a .gitattributes file. - * - * If is_macro is true, then u.attr is a pointer to the git_attr being - * defined. - * - * If is_macro is false, then u.pat is the filename pattern to which the - * rule applies. - * - * In either case, num_attr is the number of attributes affected by - * this rule, and state is an array listing them. The attributes are - * listed as they appear in the file (macros unexpanded). - */ -struct match_attr { - union { - struct pattern pat; - const struct git_attr *attr; - } u; - char is_macro; - size_t num_attr; - struct attr_state state[FLEX_ARRAY]; -}; - static const char blank[] = " \t\r\n"; /* Flags usable in read_attr() and parse_attr_line() family of functions. */ @@ -353,8 +317,8 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, return ep + strspn(ep, blank); } -static struct match_attr *parse_attr_line(const char *line, const char *src, - int lineno, unsigned flags) +struct match_attr *parse_attr_line(const char *line, const char *src, + int lineno, unsigned flags) { size_t namelen, num_attr, i; const char *cp, *name, *states; @@ -240,4 +240,47 @@ int git_attr_system_is_enabled(void); extern char *git_attr_tree; +/* + * Exposed for fuzz-testing only. + */ + +/* What does a matched pattern decide? */ +struct attr_state { + const struct git_attr *attr; + const char *setto; +}; + +struct pattern { + const char *pattern; + int patternlen; + int nowildcardlen; + unsigned flags; /* PATTERN_FLAG_* */ +}; + +/* + * One rule, as from a .gitattributes file. + * + * If is_macro is true, then u.attr is a pointer to the git_attr being + * defined. + * + * If is_macro is false, then u.pat is the filename pattern to which the + * rule applies. + * + * In either case, num_attr is the number of attributes affected by + * this rule, and state is an array listing them. The attributes are + * listed as they appear in the file (macros unexpanded). + */ +struct match_attr { + union { + struct pattern pat; + const struct git_attr *attr; + } u; + char is_macro; + size_t num_attr; + struct attr_state state[FLEX_ARRAY]; +}; + +struct match_attr *parse_attr_line(const char *line, const char *src, + int lineno, unsigned flags); + #endif /* ATTR_H */ @@ -28,8 +28,8 @@ static struct oid_array skipped_revs; static struct object_id *current_bad_oid; -static const char *term_bad; -static const char *term_good; +static char *term_bad; +static char *term_good; /* Remember to update object flag allocation in object.h */ #define COUNTED (1u<<16) @@ -443,12 +443,13 @@ void find_bisection(struct commit_list **commit_list, int *reaches, } *reaches = weight(best); } - free(weights); *commit_list = best; + + free(weights); clear_commit_weight(&commit_weight); } -static int register_ref(const char *refname, const struct object_id *oid, +static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data UNUSED) { struct strbuf good_prefix = STRBUF_INIT; @@ -456,6 +457,7 @@ static int register_ref(const char *refname, const struct object_id *oid, strbuf_addstr(&good_prefix, "-"); if (!strcmp(refname, term_bad)) { + free(current_bad_oid); current_bad_oid = xmalloc(sizeof(*current_bad_oid)); oidcpy(current_bad_oid, oid); } else if (starts_with(refname, good_prefix.buf)) { @@ -556,8 +558,11 @@ struct commit_list *filter_skipped(struct commit_list *list, tried = &list->next; } else { if (!show_all) { - if (!skipped_first || !*skipped_first) + if (!skipped_first || !*skipped_first) { + free_commit_list(next); + free_commit_list(filtered); return list; + } } else if (skipped_first && !*skipped_first) { /* This means we know it's not skipped */ *skipped_first = -1; @@ -613,7 +618,7 @@ static int sqrti(int val) static struct commit_list *skip_away(struct commit_list *list, int count) { - struct commit_list *cur, *previous; + struct commit_list *cur, *previous, *result = list; int prn, index, i; prn = get_prn(count); @@ -625,15 +630,23 @@ static struct commit_list *skip_away(struct commit_list *list, int count) for (i = 0; cur; cur = cur->next, i++) { if (i == index) { if (!oideq(&cur->item->object.oid, current_bad_oid)) - return cur; - if (previous) - return previous; - return list; + result = cur; + else if (previous) + result = previous; + else + result = list; + break; } previous = cur; } - return list; + for (cur = list; cur != result; ) { + struct commit_list *next = cur->next; + free(cur); + cur = next; + } + + return result; } static struct commit_list *managed_skipped(struct commit_list *list, @@ -801,6 +814,8 @@ static enum bisect_error handle_bad_merge_base(void) "between %s and [%s].\n"), bad_hex, term_bad, term_good, bad_hex, good_hex); } + + free(good_hex); return BISECT_MERGE_BASE_CHECK; } @@ -848,8 +863,8 @@ static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int rev + 1, &result) < 0) exit(128); - for (; result; result = result->next) { - const struct object_id *mb = &result->item->object.oid; + for (struct commit_list *l = result; l; l = l->next) { + const struct object_id *mb = &l->item->object.oid; if (oideq(mb, current_bad_oid)) { res = handle_bad_merge_base(); break; @@ -985,7 +1000,7 @@ static void show_commit(struct commit *commit) * We read them and store them to adapt the messages accordingly. * Default is bad/good. */ -void read_bisect_terms(const char **read_bad, const char **read_good) +void read_bisect_terms(char **read_bad, char **read_good) { struct strbuf str = STRBUF_INIT; const char *filename = git_path_bisect_terms(); @@ -993,16 +1008,20 @@ void read_bisect_terms(const char **read_bad, const char **read_good) if (!fp) { if (errno == ENOENT) { - *read_bad = "bad"; - *read_good = "good"; + free(*read_bad); + *read_bad = xstrdup("bad"); + free(*read_good); + *read_good = xstrdup("good"); return; } else { die_errno(_("could not read file '%s'"), filename); } } else { strbuf_getline_lf(&str, fp); + free(*read_bad); *read_bad = strbuf_detach(&str, NULL); strbuf_getline_lf(&str, fp); + free(*read_good); *read_good = strbuf_detach(&str, NULL); } strbuf_release(&str); @@ -1024,7 +1043,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) { struct strvec rev_argv = STRVEC_INIT; struct rev_info revs = REV_INFO_INIT; - struct commit_list *tried; + struct commit_list *tried = NULL; int reaches = 0, all = 0, nr, steps; enum bisect_error res = BISECT_OK; struct object_id *bisect_rev; @@ -1091,7 +1110,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) if (oideq(bisect_rev, current_bad_oid)) { res = error_if_skipped_commits(tried, current_bad_oid); if (res) - return res; + goto cleanup; printf("%s is the first %s commit\n", oid_to_hex(bisect_rev), term_bad); @@ -1125,21 +1144,12 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) res = bisect_checkout(bisect_rev, no_checkout); cleanup: + free_commit_list(tried); release_revisions(&revs); strvec_clear(&rev_argv); return res; } -static inline int log2i(int n) -{ - int log2 = 0; - - for (; n > 1; n >>= 1) - log2++; - - return log2; -} - static inline int exp2i(int n) { return 1 << n; @@ -1162,7 +1172,7 @@ int estimate_bisect_steps(int all) if (all < 3) return 0; - n = log2i(all); + n = log2u(all); e = exp2i(n); x = all - e; @@ -1170,6 +1180,7 @@ int estimate_bisect_steps(int all) } static int mark_for_removal(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cb_data) { @@ -75,7 +75,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix); int estimate_bisect_steps(int all); -void read_bisect_terms(const char **bad, const char **good); +void read_bisect_terms(char **bad, char **good); int bisect_clean_state(void); @@ -2931,6 +2931,7 @@ void setup_blame_bloom_data(struct blame_scoreboard *sb) void cleanup_scoreboard(struct blame_scoreboard *sb) { free(sb->lineno); + free(sb->final_buf); clear_prio_queue(&sb->commits); oidset_clear(&sb->ignore_list); @@ -116,7 +116,7 @@ struct blame_scoreboard { * Used by many functions to obtain contents of the nth line, * indexed with scoreboard.lineno[blame_entry.lno]. */ - const char *final_buf; + char *final_buf; unsigned long final_buf_size; /* linked list of blames */ diff --git a/block-sha1/sha1.h b/block-sha1/sha1.h index 9fb0441b98..47bb916636 100644 --- a/block-sha1/sha1.h +++ b/block-sha1/sha1.h @@ -16,7 +16,9 @@ void blk_SHA1_Init(blk_SHA_CTX *ctx); void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, size_t len); void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx); +#ifndef platform_SHA_CTX #define platform_SHA_CTX blk_SHA_CTX #define platform_SHA1_Init blk_SHA1_Init #define platform_SHA1_Update blk_SHA1_Update #define platform_SHA1_Final blk_SHA1_Final +#endif @@ -476,8 +476,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r, *last_slash = '\0'; } while (*path); - - diff_free_filepair(diff_queued_diff.queue[i]); } if (hashmap_get_size(&pathmap) > settings->max_changed_paths) { @@ -508,8 +506,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r, cleanup: hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry); } else { - for (i = 0; i < diff_queued_diff.nr; i++) - diff_free_filepair(diff_queued_diff.queue[i]); init_truncated_large_filter(filter, settings->hash_version); if (computed) @@ -519,9 +515,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r, if (computed) *computed |= BLOOM_COMPUTED; - free(diff_queued_diff.queue); - DIFF_QUEUE_CLEAR(&diff_queued_diff); - + diff_queue_clear(&diff_queued_diff); return filter; } @@ -18,7 +18,7 @@ struct bloom_filter_settings { /* * The number of times a path is hashed, i.e. the - * number of bit positions tht cumulatively + * number of bit positions that cumulatively * determine whether a path is present in the * Bloom filter. */ @@ -372,7 +372,7 @@ int read_branch_desc(struct strbuf *buf, const char *branch_name) */ int validate_branchname(const char *name, struct strbuf *ref) { - if (strbuf_check_branch_ref(ref, name)) { + if (check_branch_ref(ref, name)) { int code = die_message(_("'%s' is not a valid branch name"), name); advise_if_enabled(ADVICE_REF_SYNTAX, _("See `man git check-ref-format`")); @@ -601,6 +601,7 @@ void create_branch(struct repository *r, int forcing = 0; struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; + int flags = 0; char *msg; if (track == BRANCH_TRACK_OVERRIDE) @@ -619,18 +620,18 @@ void create_branch(struct repository *r, goto cleanup; if (reflog) - log_all_ref_updates = LOG_REFS_NORMAL; + flags |= REF_FORCE_CREATE_REFLOG; if (forcing) msg = xstrfmt("branch: Reset to %s", start_name); else msg = xstrfmt("branch: Created from %s", start_name); transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction || ref_transaction_update(transaction, ref.buf, &oid, forcing ? NULL : null_oid(), - NULL, NULL, 0, msg, &err) || + NULL, NULL, flags, msg, &err) || ref_transaction_commit(transaction, &err)) die("%s", err.buf); ref_transaction_free(transaction); @@ -737,6 +738,7 @@ static int submodule_create_branch(struct repository *r, strbuf_release(&child_err); strbuf_release(&out_buf); + free(out_prefix); return ret; } @@ -793,7 +795,7 @@ void create_branches_recursively(struct repository *r, const char *name, create_branch(r, name, start_committish, force, 0, reflog, quiet, BRANCH_TRACK_NEVER, dry_run); if (dry_run) - return; + goto out; /* * NEEDSWORK If tracking was set up in the superproject but not the * submodule, users might expect "git branch --recurse-submodules" to @@ -814,8 +816,11 @@ void create_branches_recursively(struct repository *r, const char *name, die(_("submodule '%s': cannot create branch '%s'"), submodule_entry_list.entries[i].submodule->name, name); - repo_clear(submodule_entry_list.entries[i].repo); } + +out: + submodule_entry_list_release(&submodule_entry_list); + free(branch_point); } void remove_merge_branch_state(struct repository *r) @@ -1,15 +1,8 @@ #ifndef BUILTIN_H #define BUILTIN_H -/* - * TODO: Almost all of our builtins access `the_repository` by necessity - * because they do not get passed a pointer to it. We should adapt the function - * signature of those main functions to accept a `struct repository *` and then - * remove the macro here. - */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" +#include "repository.h" /* * builtin API @@ -122,143 +115,143 @@ int is_builtin(const char *s); BUG("unexpected prefix in builtin: %s", (prefix)); \ } while (0) -int cmd_add(int argc, const char **argv, const char *prefix); -int cmd_am(int argc, const char **argv, const char *prefix); -int cmd_annotate(int argc, const char **argv, const char *prefix); -int cmd_apply(int argc, const char **argv, const char *prefix); -int cmd_archive(int argc, const char **argv, const char *prefix); -int cmd_bisect(int argc, const char **argv, const char *prefix); -int cmd_blame(int argc, const char **argv, const char *prefix); -int cmd_branch(int argc, const char **argv, const char *prefix); -int cmd_bugreport(int argc, const char **argv, const char *prefix); -int cmd_bundle(int argc, const char **argv, const char *prefix); -int cmd_cat_file(int argc, const char **argv, const char *prefix); -int cmd_checkout(int argc, const char **argv, const char *prefix); -int cmd_checkout__worker(int argc, const char **argv, const char *prefix); -int cmd_checkout_index(int argc, const char **argv, const char *prefix); -int cmd_check_attr(int argc, const char **argv, const char *prefix); -int cmd_check_ignore(int argc, const char **argv, const char *prefix); -int cmd_check_mailmap(int argc, const char **argv, const char *prefix); -int cmd_check_ref_format(int argc, const char **argv, const char *prefix); -int cmd_cherry(int argc, const char **argv, const char *prefix); -int cmd_cherry_pick(int argc, const char **argv, const char *prefix); -int cmd_clone(int argc, const char **argv, const char *prefix); -int cmd_clean(int argc, const char **argv, const char *prefix); -int cmd_column(int argc, const char **argv, const char *prefix); -int cmd_commit(int argc, const char **argv, const char *prefix); -int cmd_commit_graph(int argc, const char **argv, const char *prefix); -int cmd_commit_tree(int argc, const char **argv, const char *prefix); -int cmd_config(int argc, const char **argv, const char *prefix); -int cmd_count_objects(int argc, const char **argv, const char *prefix); -int cmd_credential(int argc, const char **argv, const char *prefix); -int cmd_credential_cache(int argc, const char **argv, const char *prefix); -int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix); -int cmd_credential_store(int argc, const char **argv, const char *prefix); -int cmd_describe(int argc, const char **argv, const char *prefix); -int cmd_diagnose(int argc, const char **argv, const char *prefix); -int cmd_diff_files(int argc, const char **argv, const char *prefix); -int cmd_diff_index(int argc, const char **argv, const char *prefix); -int cmd_diff(int argc, const char **argv, const char *prefix); -int cmd_diff_tree(int argc, const char **argv, const char *prefix); -int cmd_difftool(int argc, const char **argv, const char *prefix); -int cmd_env__helper(int argc, const char **argv, const char *prefix); -int cmd_fast_export(int argc, const char **argv, const char *prefix); -int cmd_fast_import(int argc, const char **argv, const char *prefix); -int cmd_fetch(int argc, const char **argv, const char *prefix); -int cmd_fetch_pack(int argc, const char **argv, const char *prefix); -int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); -int cmd_for_each_ref(int argc, const char **argv, const char *prefix); -int cmd_for_each_repo(int argc, const char **argv, const char *prefix); -int cmd_format_patch(int argc, const char **argv, const char *prefix); -int cmd_fsck(int argc, const char **argv, const char *prefix); -int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix); -int cmd_gc(int argc, const char **argv, const char *prefix); -int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix); -int cmd_grep(int argc, const char **argv, const char *prefix); -int cmd_hash_object(int argc, const char **argv, const char *prefix); -int cmd_help(int argc, const char **argv, const char *prefix); -int cmd_hook(int argc, const char **argv, const char *prefix); -int cmd_index_pack(int argc, const char **argv, const char *prefix); -int cmd_init_db(int argc, const char **argv, const char *prefix); -int cmd_interpret_trailers(int argc, const char **argv, const char *prefix); -int cmd_log(int argc, const char **argv, const char *prefix); -int cmd_log_reflog(int argc, const char **argv, const char *prefix); -int cmd_ls_files(int argc, const char **argv, const char *prefix); -int cmd_ls_tree(int argc, const char **argv, const char *prefix); -int cmd_ls_remote(int argc, const char **argv, const char *prefix); -int cmd_mailinfo(int argc, const char **argv, const char *prefix); -int cmd_mailsplit(int argc, const char **argv, const char *prefix); -int cmd_maintenance(int argc, const char **argv, const char *prefix); -int cmd_merge(int argc, const char **argv, const char *prefix); -int cmd_merge_base(int argc, const char **argv, const char *prefix); -int cmd_merge_index(int argc, const char **argv, const char *prefix); -int cmd_merge_ours(int argc, const char **argv, const char *prefix); -int cmd_merge_file(int argc, const char **argv, const char *prefix); -int cmd_merge_recursive(int argc, const char **argv, const char *prefix); -int cmd_merge_tree(int argc, const char **argv, const char *prefix); -int cmd_mktag(int argc, const char **argv, const char *prefix); -int cmd_mktree(int argc, const char **argv, const char *prefix); -int cmd_multi_pack_index(int argc, const char **argv, const char *prefix); -int cmd_mv(int argc, const char **argv, const char *prefix); -int cmd_name_rev(int argc, const char **argv, const char *prefix); -int cmd_notes(int argc, const char **argv, const char *prefix); -int cmd_pack_objects(int argc, const char **argv, const char *prefix); -int cmd_pack_redundant(int argc, const char **argv, const char *prefix); -int cmd_patch_id(int argc, const char **argv, const char *prefix); -int cmd_prune(int argc, const char **argv, const char *prefix); -int cmd_prune_packed(int argc, const char **argv, const char *prefix); -int cmd_pull(int argc, const char **argv, const char *prefix); -int cmd_push(int argc, const char **argv, const char *prefix); -int cmd_range_diff(int argc, const char **argv, const char *prefix); -int cmd_read_tree(int argc, const char **argv, const char *prefix); -int cmd_rebase(int argc, const char **argv, const char *prefix); -int cmd_rebase__interactive(int argc, const char **argv, const char *prefix); -int cmd_receive_pack(int argc, const char **argv, const char *prefix); -int cmd_reflog(int argc, const char **argv, const char *prefix); -int cmd_refs(int argc, const char **argv, const char *prefix); -int cmd_remote(int argc, const char **argv, const char *prefix); -int cmd_remote_ext(int argc, const char **argv, const char *prefix); -int cmd_remote_fd(int argc, const char **argv, const char *prefix); -int cmd_repack(int argc, const char **argv, const char *prefix); -int cmd_replay(int argc, const char **argv, const char *prefix); -int cmd_rerere(int argc, const char **argv, const char *prefix); -int cmd_reset(int argc, const char **argv, const char *prefix); -int cmd_restore(int argc, const char **argv, const char *prefix); -int cmd_rev_list(int argc, const char **argv, const char *prefix); -int cmd_rev_parse(int argc, const char **argv, const char *prefix); -int cmd_revert(int argc, const char **argv, const char *prefix); -int cmd_rm(int argc, const char **argv, const char *prefix); -int cmd_send_pack(int argc, const char **argv, const char *prefix); -int cmd_shortlog(int argc, const char **argv, const char *prefix); -int cmd_show(int argc, const char **argv, const char *prefix); -int cmd_show_branch(int argc, const char **argv, const char *prefix); -int cmd_show_index(int argc, const char **argv, const char *prefix); -int cmd_sparse_checkout(int argc, const char **argv, const char *prefix); -int cmd_status(int argc, const char **argv, const char *prefix); -int cmd_stash(int argc, const char **argv, const char *prefix); -int cmd_stripspace(int argc, const char **argv, const char *prefix); -int cmd_submodule__helper(int argc, const char **argv, const char *prefix); -int cmd_switch(int argc, const char **argv, const char *prefix); -int cmd_symbolic_ref(int argc, const char **argv, const char *prefix); -int cmd_tag(int argc, const char **argv, const char *prefix); -int cmd_unpack_file(int argc, const char **argv, const char *prefix); -int cmd_unpack_objects(int argc, const char **argv, const char *prefix); -int cmd_update_index(int argc, const char **argv, const char *prefix); -int cmd_update_ref(int argc, const char **argv, const char *prefix); -int cmd_update_server_info(int argc, const char **argv, const char *prefix); -int cmd_upload_archive(int argc, const char **argv, const char *prefix); -int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix); -int cmd_upload_pack(int argc, const char **argv, const char *prefix); -int cmd_var(int argc, const char **argv, const char *prefix); -int cmd_verify_commit(int argc, const char **argv, const char *prefix); -int cmd_verify_tag(int argc, const char **argv, const char *prefix); -int cmd_version(int argc, const char **argv, const char *prefix); -int cmd_whatchanged(int argc, const char **argv, const char *prefix); -int cmd_worktree(int argc, const char **argv, const char *prefix); -int cmd_write_tree(int argc, const char **argv, const char *prefix); -int cmd_verify_pack(int argc, const char **argv, const char *prefix); -int cmd_show_ref(int argc, const char **argv, const char *prefix); -int cmd_pack_refs(int argc, const char **argv, const char *prefix); -int cmd_replace(int argc, const char **argv, const char *prefix); +int cmd_add(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_am(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_annotate(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_apply(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_archive(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_bisect(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_blame(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_branch(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_bugreport(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_bundle(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_cat_file(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_checkout(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_checkout__worker(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_checkout_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_check_attr(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_check_ignore(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_check_mailmap(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_check_ref_format(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_cherry(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_cherry_pick(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_clone(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_clean(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_column(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_commit(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_commit_graph(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_commit_tree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_config(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_count_objects(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_credential(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_credential_cache(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_credential_store(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_describe(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_diagnose(int argc, const char **argv, const char *prefix, struct repository *repo); +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_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); +int cmd_fast_export(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fast_import(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fetch(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fetch_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_for_each_ref(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_for_each_repo(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_format_patch(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fsck(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_gc(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_grep(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_hash_object(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_help(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_hook(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_index_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_init_db(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_interpret_trailers(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_log_reflog(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_log(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_ls_files(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_ls_tree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_ls_remote(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_mailinfo(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_mailsplit(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_maintenance(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_base(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_ours(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_file(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_recursive(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_merge_tree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_mktag(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_mktree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_multi_pack_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_mv(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_name_rev(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_notes(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_pack_objects(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_pack_redundant(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_patch_id(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_prune(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_prune_packed(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_pull(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_push(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_range_diff(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_read_tree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rebase(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rebase__interactive(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_receive_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_reflog(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_refs(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_remote(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_remote_ext(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_remote_fd(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_repack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_replay(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rerere(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_reset(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_restore(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rev_list(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rev_parse(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_revert(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_rm(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_send_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_shortlog(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_show(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_show_branch(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_show_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_sparse_checkout(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_status(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_stash(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_stripspace(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_submodule__helper(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_switch(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_symbolic_ref(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_tag(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_unpack_file(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_unpack_objects(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_update_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_update_ref(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_update_server_info(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_upload_archive(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_upload_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_var(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_verify_commit(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_verify_tag(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_version(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_whatchanged(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_worktree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_write_tree(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_verify_pack(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_show_ref(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_pack_refs(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_replace(int argc, const char **argv, const char *prefix, struct repository *repo); #endif diff --git a/builtin/add.c b/builtin/add.c index 40b61ef90d..7d35307792 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -3,7 +3,6 @@ * * Copyright (C) 2006 Linus Torvalds */ - #include "builtin.h" #include "advice.h" #include "config.h" @@ -18,7 +17,6 @@ #include "preload-index.h" #include "diff.h" #include "read-cache.h" -#include "repository.h" #include "revision.h" #include "bulk-checkin.h" #include "strvec.h" @@ -36,24 +34,27 @@ static int pathspec_file_nul; static int include_sparse; static const char *pathspec_from_file; -static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) +static int chmod_pathspec(struct repository *repo, + struct pathspec *pathspec, + char flip, + int show_only) { int i, ret = 0; - for (i = 0; i < the_repository->index->cache_nr; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < repo->index->cache_nr; i++) { + struct cache_entry *ce = repo->index->cache[i]; int err; if (!include_sparse && (ce_skip_worktree(ce) || - !path_in_sparse_checkout(ce->name, the_repository->index))) + !path_in_sparse_checkout(ce->name, repo->index))) continue; - if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL)) + if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL)) continue; if (!show_only) - err = chmod_index_entry(the_repository->index, ce, flip); + err = chmod_index_entry(repo->index, ce, flip); else err = S_ISREG(ce->ce_mode) ? 0 : -1; @@ -64,31 +65,36 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) return ret; } -static int renormalize_tracked_files(const struct pathspec *pathspec, int flags) +static int renormalize_tracked_files(struct repository *repo, + const struct pathspec *pathspec, + int flags) { int i, retval = 0; - for (i = 0; i < the_repository->index->cache_nr; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < repo->index->cache_nr; i++) { + struct cache_entry *ce = repo->index->cache[i]; if (!include_sparse && (ce_skip_worktree(ce) || - !path_in_sparse_checkout(ce->name, the_repository->index))) + !path_in_sparse_checkout(ce->name, repo->index))) continue; if (ce_stage(ce)) continue; /* do not touch unmerged paths */ if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode)) continue; /* do not touch non blobs */ - if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL)) + if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL)) continue; - retval |= add_file_to_index(the_repository->index, ce->name, + retval |= add_file_to_index(repo->index, ce->name, flags | ADD_CACHE_RENORMALIZE); } return retval; } -static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix) +static char *prune_directory(struct repository *repo, + struct dir_struct *dir, + struct pathspec *pathspec, + int prefix) { char *seen; int i; @@ -100,16 +106,16 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, i = dir->nr; while (--i >= 0) { struct dir_entry *entry = *src++; - if (dir_path_match(the_repository->index, entry, pathspec, prefix, seen)) + if (dir_path_match(repo->index, entry, pathspec, prefix, seen)) *dst++ = entry; } dir->nr = dst - dir->entries; - add_pathspec_matches_against_index(pathspec, the_repository->index, seen, + add_pathspec_matches_against_index(pathspec, repo->index, seen, PS_IGNORE_SKIP_WORKTREE); return seen; } -static int refresh(int verbose, const struct pathspec *pathspec) +static int refresh(struct repository *repo, int verbose, const struct pathspec *pathspec) { char *seen; int i, ret = 0; @@ -119,14 +125,14 @@ static int refresh(int verbose, const struct pathspec *pathspec) (verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET); seen = xcalloc(pathspec->nr, 1); - refresh_index(the_repository->index, flags, pathspec, seen, + refresh_index(repo->index, flags, pathspec, seen, _("Unstaged changes after refreshing the index:")); for (i = 0; i < pathspec->nr; i++) { if (!seen[i]) { const char *path = pathspec->items[i].original; if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) || - !path_in_sparse_checkout(path, the_repository->index)) { + !path_in_sparse_checkout(path, repo->index)) { string_list_append(&only_match_skip_worktree, pathspec->items[i].original); } else { @@ -147,7 +153,10 @@ static int refresh(int verbose, const struct pathspec *pathspec) return ret; } -int interactive_add(const char **argv, const char *prefix, int patch) +int interactive_add(struct repository *repo, + const char **argv, + const char *prefix, + int patch) { struct pathspec pathspec; int ret; @@ -159,28 +168,31 @@ int interactive_add(const char **argv, const char *prefix, int patch) prefix, argv); if (patch) - ret = !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec); + ret = !!run_add_p(repo, ADD_P_ADD, NULL, &pathspec); else - ret = !!run_add_i(the_repository, &pathspec); + ret = !!run_add_i(repo, &pathspec); clear_pathspec(&pathspec); return ret; } -static int edit_patch(int argc, const char **argv, const char *prefix) +static int edit_patch(struct repository *repo, + int argc, + const char **argv, + const char *prefix) { - char *file = git_pathdup("ADD_EDIT.patch"); + char *file = repo_git_path(repo, "ADD_EDIT.patch"); struct child_process child = CHILD_PROCESS_INIT; struct rev_info rev; int out; struct stat st; - git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ + repo_config(repo, git_diff_basic_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die(_("could not read the index")); - repo_init_revisions(the_repository, &rev, prefix); + repo_init_revisions(repo, &rev, prefix); rev.diffopt.context = 7; argc = setup_revisions(argc, argv, &rev, NULL); @@ -318,7 +330,7 @@ static void check_embedded_repo(const char *path) strbuf_release(&name); } -static int add_files(struct dir_struct *dir, int flags) +static int add_files(struct repository *repo, struct dir_struct *dir, int flags) { int i, exit_status = 0; struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP; @@ -334,12 +346,12 @@ static int add_files(struct dir_struct *dir, int flags) for (i = 0; i < dir->nr; i++) { if (!include_sparse && - !path_in_sparse_checkout(dir->entries[i]->name, the_repository->index)) { + !path_in_sparse_checkout(dir->entries[i]->name, repo->index)) { string_list_append(&matched_sparse_paths, dir->entries[i]->name); continue; } - if (add_file_to_index(the_repository->index, dir->entries[i]->name, flags)) { + if (add_file_to_index(repo->index, dir->entries[i]->name, flags)) { if (!ignore_add_errors) die(_("adding files failed")); exit_status = 1; @@ -358,7 +370,10 @@ static int add_files(struct dir_struct *dir, int flags) return exit_status; } -int cmd_add(int argc, const char **argv, const char *prefix) +int cmd_add(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { int exit_status = 0; struct pathspec pathspec; @@ -370,7 +385,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) char *ps_matched = NULL; struct lock_file lock_file = LOCK_INIT; - git_config(add_config, NULL); + if (repo) + repo_config(repo, add_config, NULL); argc = parse_options(argc, argv, prefix, builtin_add_options, builtin_add_usage, PARSE_OPT_KEEP_ARGV0); @@ -381,13 +397,13 @@ int cmd_add(int argc, const char **argv, const char *prefix) die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch"); if (pathspec_from_file) die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch"); - exit(interactive_add(argv + 1, prefix, patch_interactive)); + exit(interactive_add(repo, argv + 1, prefix, patch_interactive)); } if (edit_interactive) { if (pathspec_from_file) die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit"); - return(edit_patch(argc, argv, prefix)); + return(edit_patch(repo, argc, argv, prefix)); } argc--; argv++; @@ -410,10 +426,10 @@ int cmd_add(int argc, const char **argv, const char *prefix) add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize; require_pathspec = !(take_worktree_changes || (0 < addremove_explicit)); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); /* * Check the "pathspec '%s' did not match any files" block @@ -454,11 +470,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) (!(addremove || take_worktree_changes) ? ADD_CACHE_IGNORE_REMOVAL : 0)); - if (repo_read_index_preload(the_repository, &pathspec, 0) < 0) + if (repo_read_index_preload(repo, &pathspec, 0) < 0) die(_("index file corrupt")); - die_in_unpopulated_submodule(the_repository->index, prefix); - die_path_inside_submodule(the_repository->index, &pathspec); + die_in_unpopulated_submodule(repo->index, prefix); + die_path_inside_submodule(repo->index, &pathspec); if (add_new_files) { int baselen; @@ -470,13 +486,13 @@ int cmd_add(int argc, const char **argv, const char *prefix) } /* This picks up the paths that are not tracked */ - baselen = fill_directory(&dir, the_repository->index, &pathspec); + baselen = fill_directory(&dir, repo->index, &pathspec); if (pathspec.nr) - seen = prune_directory(&dir, &pathspec, baselen); + seen = prune_directory(repo, &dir, &pathspec, baselen); } if (refresh_only) { - exit_status |= refresh(verbose, &pathspec); + exit_status |= refresh(repo, verbose, &pathspec); goto finish; } @@ -487,7 +503,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (!seen) seen = find_pathspecs_matching_against_index(&pathspec, - the_repository->index, PS_IGNORE_SKIP_WORKTREE); + repo->index, PS_IGNORE_SKIP_WORKTREE); /* * file_exists() assumes exact match @@ -523,8 +539,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) !file_exists(path)) { if (ignore_missing) { int dtype = DT_UNKNOWN; - if (is_excluded(&dir, the_repository->index, path, &dtype)) - dir_add_ignored(&dir, the_repository->index, + if (is_excluded(&dir, repo->index, path, &dtype)) + dir_add_ignored(&dir, repo->index, path, pathspec.items[i].len); } else die(_("pathspec '%s' did not match any files"), @@ -547,9 +563,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) ps_matched = xcalloc(pathspec.nr, 1); if (add_renormalize) - exit_status |= renormalize_tracked_files(&pathspec, flags); + exit_status |= renormalize_tracked_files(repo, &pathspec, flags); else - exit_status |= add_files_to_cache(the_repository, prefix, + exit_status |= add_files_to_cache(repo, prefix, &pathspec, ps_matched, include_sparse, flags); @@ -558,14 +574,14 @@ int cmd_add(int argc, const char **argv, const char *prefix) exit(128); if (add_new_files) - exit_status |= add_files(&dir, flags); + exit_status |= add_files(repo, &dir, flags); if (chmod_arg && pathspec.nr) - exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only); + exit_status |= chmod_pathspec(repo, &pathspec, chmod_arg[0], show_only); end_odb_transaction(); finish: - if (write_locked_index(the_repository->index, &lock_file, + if (write_locked_index(repo->index, &lock_file, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write new index file")); diff --git a/builtin/am.c b/builtin/am.c index 370f5593f2..bfa95147cf 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -4,6 +4,7 @@ * Based on git-am.sh by Junio C Hamano. */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "advice.h" @@ -38,7 +39,6 @@ #include "string-list.h" #include "pager.h" #include "path.h" -#include "repository.h" #include "pretty.h" /** @@ -490,7 +490,8 @@ static int run_applypatch_msg_hook(struct am_state *state) assert(state->msg); if (!state->no_verify) - ret = run_hooks_l("applypatch-msg", am_path(state, "final-commit"), NULL); + ret = run_hooks_l(the_repository, "applypatch-msg", + am_path(state, "final-commit"), NULL); if (!ret) { FREE_AND_NULL(state->msg); @@ -512,7 +513,7 @@ static int run_post_rewrite_hook(const struct am_state *state) strvec_push(&opt.args, "rebase"); opt.path_to_stdin = am_path(state, "rewritten"); - return run_hooks_opt("post-rewrite", &opt); + return run_hooks_opt(the_repository, "post-rewrite", &opt); } /** @@ -1543,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file) if (index_file) { /* Reload index as apply_all_patches() will have modified it. */ discard_index(the_repository->index); - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, + repo_get_git_dir(the_repository)); } return 0; @@ -1586,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa return error("could not build fake ancestor"); discard_index(the_repository->index); - read_index_from(the_repository->index, index_path, get_git_dir()); + read_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository)); if (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL)) return error(_("Repository lacks necessary blobs to fall back on 3-way merge.")); @@ -1630,7 +1632,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa * changes. */ - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); @@ -1663,10 +1665,12 @@ static void do_commit(const struct am_state *state) const char *reflog_msg, *author, *committer = NULL; struct strbuf sb = STRBUF_INIT; - if (!state->no_verify && run_hooks("pre-applypatch")) + if (!state->no_verify && run_hooks(the_repository, "pre-applypatch")) exit(1); - if (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(&tree, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) die(_("git write-tree failed to write a tree")); if (!repo_get_oid_commit(the_repository, "HEAD", &parent)) { @@ -1716,7 +1720,7 @@ static void do_commit(const struct am_state *state) fclose(fp); } - run_hooks("post-applypatch"); + run_hooks(the_repository, "post-applypatch"); free_commit_list(parents); strbuf_release(&sb); @@ -2076,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem if (fast_forward_to(head_tree, head_tree, 1)) return -1; - if (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(&index, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) return -1; index_tree = parse_tree_indirect(&index); @@ -2297,7 +2303,10 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar return 0; } -int cmd_am(int argc, const char **argv, const char *prefix) +int cmd_am(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct am_state state; int binary = -1; diff --git a/builtin/annotate.c b/builtin/annotate.c index 58ff977a23..7f754f2309 100644 --- a/builtin/annotate.c +++ b/builtin/annotate.c @@ -3,20 +3,34 @@ * * Copyright (C) 2006 Ryan Anderson */ + #include "git-compat-util.h" #include "builtin.h" #include "strvec.h" -int cmd_annotate(int argc, const char **argv, const char *prefix) +int cmd_annotate(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { struct strvec args = STRVEC_INIT; - int i; + const char **args_copy; + int ret; strvec_pushl(&args, "annotate", "-c", NULL); - - for (i = 1; i < argc; i++) { + for (int i = 1; i < argc; i++) strvec_push(&args, argv[i]); - } - return cmd_blame(args.nr, args.v, prefix); + /* + * `cmd_blame()` ends up modifying the array, which causes memory leaks + * if we didn't copy the array here. + */ + CALLOC_ARRAY(args_copy, args.nr + 1); + COPY_ARRAY(args_copy, args.v, args.nr); + + ret = cmd_blame(args.nr, args_copy, prefix, repo); + + strvec_clear(&args); + free(args_copy); + return ret; } diff --git a/builtin/apply.c b/builtin/apply.c index d623c52f78..84f1863d3a 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1,6 +1,6 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" -#include "repository.h" #include "hash.h" #include "apply.h" @@ -9,7 +9,10 @@ static const char * const apply_usage[] = { NULL }; -int cmd_apply(int argc, const char **argv, const char *prefix) +int cmd_apply(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force_apply = 0; int options = 0; diff --git a/builtin/archive.c b/builtin/archive.c index b50981504f..13ea7308c8 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -8,7 +8,6 @@ #include "transport.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" static void create_output_file(const char *output_file) { @@ -76,7 +75,10 @@ static int run_remote_archiver(int argc, const char **argv, PARSE_OPT_KEEP_UNKNOWN_OPT | \ PARSE_OPT_NO_INTERNAL_HELP ) -int cmd_archive(int argc, const char **argv, const char *prefix) +int cmd_archive(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { const char *exec = "git-upload-archive"; char *output = NULL; @@ -100,13 +102,16 @@ int cmd_archive(int argc, const char **argv, const char *prefix) if (output) create_output_file(output); - if (remote) - return run_remote_archiver(argc, argv, remote, exec, output); + if (remote) { + ret = run_remote_archiver(argc, argv, remote, exec, output); + goto out; + } setvbuf(stderr, NULL, _IOLBF, BUFSIZ); - ret = write_archive(argc, argv, prefix, the_repository, output, 0); + ret = write_archive(argc, argv, prefix, repo, output, 0); +out: free(output); return ret; } diff --git a/builtin/bisect.c b/builtin/bisect.c index dabce9b542..8166d4abf5 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "copy.h" #include "environment.h" @@ -356,6 +357,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) } static int inc_nr(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cb_data) { @@ -545,7 +547,7 @@ finish: return res; } -static int add_bisect_ref(const char *refname, const struct object_id *oid, +static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb) { struct add_bisect_ref_data *data = cb; @@ -582,7 +584,7 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs) refs_for_each_glob_ref_in(get_main_ref_store(the_repository), add_bisect_ref, good, "refs/bisect/", &cb); if (prepare_revision_walk(revs)) - res = error(_("revision walk setup failed\n")); + res = error(_("revision walk setup failed")); free(good); free(bad); @@ -1107,7 +1109,7 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, int argc, setup_revisions(2, argv + i - 1, &revs, NULL); if (prepare_revision_walk(&revs)) - die(_("revision walk setup failed\n")); + die(_("revision walk setup failed")); while ((commit = get_revision(&revs)) != NULL) strvec_push(&argv_state, oid_to_hex(&commit->object.oid)); @@ -1162,6 +1164,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc, } static int get_first_good(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -1309,7 +1312,8 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv) return res; } -static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { if (argc > 1) return error(_("'%s' requires either no argument or a commit"), @@ -1317,7 +1321,8 @@ static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNU return bisect_reset(argc ? argv[0] : NULL); } -static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1330,7 +1335,8 @@ static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNU return res; } -static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1341,7 +1347,8 @@ static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNU return res; } -static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *prefix) +static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *prefix, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1355,12 +1362,15 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref return res; } -static int cmd_bisect__log(int argc UNUSED, const char **argv UNUSED, const char *prefix UNUSED) +static int cmd_bisect__log(int argc UNUSED, const char **argv UNUSED, + const char *prefix UNUSED, + struct repository *repo UNUSED) { return bisect_log(); } -static int cmd_bisect__replay(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__replay(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1373,7 +1383,8 @@ static int cmd_bisect__replay(int argc, const char **argv, const char *prefix UN return res; } -static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1385,7 +1396,8 @@ static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUS return res; } -static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1396,7 +1408,8 @@ static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix return res; } -static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSED) +static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int res; struct bisect_terms terms = { 0 }; @@ -1409,7 +1422,10 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE return res; } -int cmd_bisect(int argc, const char **argv, const char *prefix) +int cmd_bisect(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { int res = 0; parse_opt_subcommand_fn *fn = NULL; @@ -1445,7 +1461,7 @@ int cmd_bisect(int argc, const char **argv, const char *prefix) } else { argc--; argv++; - res = fn(argc, argv, prefix); + res = fn(argc, argv, prefix, repo); } return is_bisect_success(res) ? 0 : -res; diff --git a/builtin/blame.c b/builtin/blame.c index 35e975fb13..6a7bb3b072 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -4,7 +4,7 @@ * Copyright (c) 2006, 2014 by its authors * See COPYING for licensing conditions */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "color.h" @@ -12,7 +12,6 @@ #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "commit.h" #include "diff.h" #include "revision.h" @@ -864,7 +863,10 @@ static void build_ignorelist(struct blame_scoreboard *sb, } } -int cmd_blame(int argc, const char **argv, const char *prefix) +int cmd_blame(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; char *path = NULL; @@ -1081,7 +1083,7 @@ parse_done: path = add_prefix(prefix, argv[1]); argv[1] = argv[2]; } else { /* (2a) */ - if (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree()) + if (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository)) die("missing <path> to blame"); path = add_prefix(prefix, argv[argc - 1]); } @@ -1214,12 +1216,6 @@ parse_done: output_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR); output(&sb, output_option); - free((void *)sb.final_buf); - for (ent = sb.ent; ent; ) { - struct blame_entry *e = ent->next; - free(ent); - ent = e; - } if (show_stats) { printf("num read blob: %d\n", sb.num_read_blob); @@ -1228,6 +1224,12 @@ parse_done: } cleanup: + for (ent = sb.ent; ent; ) { + struct blame_entry *e = ent->next; + free(ent); + ent = e; + } + free(path); cleanup_scoreboard(&sb); release_revisions(&revs); diff --git a/builtin/branch.c b/builtin/branch.c index 48cac74f97..200909c23e 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -4,7 +4,7 @@ * Copyright (c) 2006 Kristian Høgsberg <krh@redhat.com> * Based on git-branch.sh by Junio C Hamano. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "color.h" @@ -210,7 +210,7 @@ static void delete_branch_config(const char *branchname) { struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "branch.%s", branchname); - if (git_config_rename_section(buf.buf, NULL) < 0) + if (repo_config_rename_section(the_repository, buf.buf, NULL) < 0) warning(_("update of config-file failed")); strbuf_release(&buf); } @@ -257,7 +257,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, char *target = NULL; int flags = 0; - strbuf_branchname(&bname, argv[i], allowed_interpret); + copy_branchname(&bname, argv[i], allowed_interpret); free(name); name = mkpathdup(fmt, bname.buf); @@ -579,7 +579,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int int recovery = 0, oldref_usage = 0; struct worktree **worktrees = get_worktrees(); - if (strbuf_check_branch_ref(&oldref, oldname)) { + if (check_branch_ref(&oldref, oldname)) { /* * Bad name --- this could be an attempt to rename a * ref that we used to allow to be created by accident. @@ -659,9 +659,10 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int strbuf_addf(&oldsection, "branch.%s", interpreted_oldname); strbuf_addf(&newsection, "branch.%s", interpreted_newname); - if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0) + if (!copy && repo_config_rename_section(the_repository, oldsection.buf, newsection.buf) < 0) die(_("branch is renamed, but update of config-file failed")); - if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0) + if (copy && strcmp(interpreted_oldname, interpreted_newname) && + repo_config_copy_section(the_repository, oldsection.buf, newsection.buf) < 0) die(_("branch is copied, but update of config-file failed")); strbuf_release(&oldref); strbuf_release(&newref); @@ -703,7 +704,10 @@ static int edit_branch_description(const char *branch_name) return 0; } -int cmd_branch(int argc, const char **argv, const char *prefix) +int cmd_branch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { /* possible actions */ int delete = 0, rename = 0, copy = 0, list = 0, @@ -718,6 +722,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) static struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; struct ref_format format = REF_FORMAT_INIT; + int ret; struct option options[] = { OPT_GROUP(N_("Generic options")), @@ -847,15 +852,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (list) setup_auto_pager("branch", 1); - UNLEAK(sorting_options); - if (delete) { if (!argc) die(_("branch name required")); - return delete_branches(argc, argv, delete > 1, filter.kind, quiet); + ret = delete_branches(argc, argv, delete > 1, filter.kind, quiet); + goto out; } else if (show_current) { print_current_branch_name(); - return 0; + ret = 0; + goto out; } else if (list) { /* git branch --list also shows HEAD when it is detached */ if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached) @@ -877,37 +882,43 @@ int cmd_branch(int argc, const char **argv, const char *prefix) string_list_clear(&output, 0); ref_sorting_release(sorting); ref_filter_clear(&filter); - return 0; + ref_format_clear(&format); + + ret = 0; + goto out; } else if (edit_description) { const char *branch_name; struct strbuf branch_ref = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; - int ret = 1; /* assume failure */ if (!argc) { if (filter.detached) die(_("cannot give description to detached HEAD")); branch_name = head; } else if (argc == 1) { - strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); branch_name = buf.buf; } else { die(_("cannot edit description of more than one branch")); } strbuf_addf(&branch_ref, "refs/heads/%s", branch_name); - if (!refs_ref_exists(get_main_ref_store(the_repository), branch_ref.buf)) + if (!refs_ref_exists(get_main_ref_store(the_repository), branch_ref.buf)) { error((!argc || branch_checked_out(branch_ref.buf)) ? _("no commit on branch '%s' yet") : _("no branch named '%s'"), branch_name); - else if (!edit_branch_description(branch_name)) + ret = 1; + } else if (!edit_branch_description(branch_name)) { ret = 0; /* happy */ + } else { + ret = 1; + } strbuf_release(&branch_ref); strbuf_release(&buf); - return ret; + goto out; } else if (copy || rename) { if (!argc) die(_("branch name required")); @@ -928,7 +939,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) branch = branch_get(NULL); else if (argc == 1) { - strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); branch = branch_get(buf.buf); } else die(_("too many arguments to set new upstream")); @@ -958,7 +969,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!argc) branch = branch_get(NULL); else if (argc == 1) { - strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); branch = branch_get(buf.buf); } else die(_("too many arguments to unset upstream")); @@ -995,12 +1006,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix) create_branches_recursively(the_repository, branch_name, start_name, NULL, force, reflog, quiet, track, 0); - return 0; + ret = 0; + goto out; } create_branch(the_repository, branch_name, start_name, force, 0, reflog, quiet, track, 0); } else usage_with_options(builtin_branch_usage, options); - return 0; + ret = 0; + +out: + string_list_clear(&sorting_options, 0); + return ret; } diff --git a/builtin/bugreport.c b/builtin/bugreport.c index b3cc77af53..7c2df035c9 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "editor.h" @@ -58,7 +59,7 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit) for (p = hook_name_list; *p; p++) { const char *hook = *p; - if (hook_exists(hook)) + if (hook_exists(the_repository, hook)) strbuf_addf(hook_info, "%s\n", hook); } } @@ -98,7 +99,10 @@ static void get_header(struct strbuf *buf, const char *title) strbuf_addf(buf, "\n\n[%s]\n", title); } -int cmd_bugreport(int argc, const char **argv, const char *prefix) +int cmd_bugreport(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buffer = STRBUF_INIT; struct strbuf report_path = STRBUF_INIT; diff --git a/builtin/bundle.c b/builtin/bundle.c index d5d41a8f67..1e170e9278 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" @@ -5,7 +6,6 @@ #include "strvec.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" #include "bundle.h" /* @@ -67,7 +67,8 @@ static int parse_options_cmd_bundle(int argc, return argc; } -static int cmd_bundle_create(int argc, const char **argv, const char *prefix) { +static int cmd_bundle_create(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct strvec pack_opts = STRVEC_INIT; int version = -1; int ret; @@ -123,7 +124,8 @@ static int open_bundle(const char *path, struct bundle_header *header, return read_bundle_header(path, header); } -static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) { +static int cmd_bundle_verify(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct bundle_header header = BUNDLE_HEADER_INIT; int bundle_fd = -1; int quiet = 0; @@ -164,7 +166,8 @@ cleanup: return ret; } -static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) { +static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct bundle_header header = BUNDLE_HEADER_INIT; int bundle_fd = -1; int ret; @@ -189,7 +192,8 @@ cleanup: return ret; } -static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) { +static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct bundle_header header = BUNDLE_HEADER_INIT; int bundle_fd = -1; int ret; @@ -207,25 +211,31 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) builtin_bundle_unbundle_usage, options, &bundle_file); /* bundle internals use argv[1] as further parameters */ + if (!startup_info->have_repository) + die(_("Need a repository to unbundle.")); + if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) { ret = 1; goto cleanup; } - if (!startup_info->have_repository) - die(_("Need a repository to unbundle.")); if (progress) strvec_pushl(&extra_index_pack_args, "-v", "--progress-title", _("Unbundling objects"), NULL); ret = !!unbundle(the_repository, &header, bundle_fd, - &extra_index_pack_args, 0) || + &extra_index_pack_args, NULL) || list_bundle_refs(&header, argc, argv); bundle_header_release(&header); + cleanup: + strvec_clear(&extra_index_pack_args); free(bundle_file); return ret; } -int cmd_bundle(int argc, const char **argv, const char *prefix) +int cmd_bundle(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { @@ -241,5 +251,5 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) packet_trace_identity("bundle"); - return !!fn(argc, argv, prefix); + return !!fn(argc, argv, prefix, repo); } diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 18fe58d6b8..d67b101c20 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "convert.h" @@ -191,7 +191,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, const char *ls_args[3] = { NULL }; ls_args[0] = "ls-tree"; ls_args[1] = obj_name; - ret = cmd_ls_tree(2, ls_args, NULL); + ret = cmd_ls_tree(2, ls_args, NULL, the_repository); goto cleanup; } @@ -827,15 +827,16 @@ static int batch_objects(struct batch_options *opt) cb.seen = &seen; for_each_loose_object(batch_unordered_loose, &cb, 0); - for_each_packed_object(batch_unordered_packed, &cb, - FOR_EACH_OBJECT_PACK_ORDER); + for_each_packed_object(the_repository, batch_unordered_packed, + &cb, FOR_EACH_OBJECT_PACK_ORDER); oidset_clear(&seen); } else { struct oid_array sa = OID_ARRAY_INIT; for_each_loose_object(collect_loose_object, &sa, 0); - for_each_packed_object(collect_packed_object, &sa, 0); + for_each_packed_object(the_repository, collect_packed_object, + &sa, 0); oid_array_for_each_unique(&sa, batch_object_cb, &cb); @@ -923,7 +924,10 @@ static int batch_option_callback(const struct option *opt, return 0; } -int cmd_cat_file(int argc, const char **argv, const char *prefix) +int cmd_cat_file(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int opt = 0; int opt_cw = 0; @@ -1047,6 +1051,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) if (batch.buffer_output < 0) batch.buffer_output = batch.all_objects; + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + /* Return early if we're in batch mode? */ if (batch.enabled) { if (opt_cw) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 9376810710..7cf275b893 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "attr.h" @@ -5,7 +6,6 @@ #include "gettext.h" #include "object-name.h" #include "quote.h" -#include "repository.h" #include "setup.h" #include "parse-options.h" #include "write-or-die.h" @@ -107,7 +107,10 @@ static NORETURN void error_with_usage(const char *msg) usage_with_options(check_attr_usage, check_attr_options); } -int cmd_check_attr(int argc, const char **argv, const char *prefix) +int cmd_check_attr(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct attr_check *check; struct object_id initialized_oid; diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 2bda6a1d46..7b7831d13a 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -5,7 +6,6 @@ #include "quote.h" #include "pathspec.h" #include "parse-options.h" -#include "repository.h" #include "submodule.h" #include "write-or-die.h" @@ -151,7 +151,10 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix) return num_ignored; } -int cmd_check_ignore(int argc, const char **argv, const char *prefix) +int cmd_check_ignore(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int num_ignored; struct dir_struct dir = DIR_INIT; diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index b8a05b8e07..df00b5ee13 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -9,6 +10,7 @@ #include "write-or-die.h" static int use_stdin; +static const char *mailmap_file, *mailmap_blob; static const char * const check_mailmap_usage[] = { N_("git check-mailmap [<options>] <contact>..."), NULL @@ -16,6 +18,8 @@ NULL static const struct option check_mailmap_options[] = { OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")), + OPT_FILENAME(0, "mailmap-file", &mailmap_file, N_("read additional mailmap entries from file")), + OPT_STRING(0, "mailmap-blob", &mailmap_blob, N_("blob"), N_("read additional mailmap entries from blob")), OPT_END() }; @@ -25,13 +29,17 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) size_t namelen, maillen; struct ident_split ident; - if (split_ident_line(&ident, contact, strlen(contact))) - die(_("unable to parse contact: %s"), contact); - - name = ident.name_begin; - namelen = ident.name_end - ident.name_begin; - mail = ident.mail_begin; - maillen = ident.mail_end - ident.mail_begin; + if (!split_ident_line(&ident, contact, strlen(contact))) { + name = ident.name_begin; + namelen = ident.name_end - ident.name_begin; + mail = ident.mail_begin; + maillen = ident.mail_end - ident.mail_begin; + } else { + name = NULL; + namelen = 0; + mail = contact; + maillen = strlen(contact); + } map_user(mailmap, &mail, &maillen, &name, &namelen); @@ -40,7 +48,10 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) printf("<%.*s>\n", (int)maillen, mail); } -int cmd_check_mailmap(int argc, const char **argv, const char *prefix) +int cmd_check_mailmap(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct string_list mailmap = STRING_LIST_INIT_NODUP; @@ -52,6 +63,10 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix) die(_("no contacts specified")); read_mailmap(&mailmap); + if (mailmap_blob) + read_mailmap_blob(&mailmap, mailmap_blob); + if (mailmap_file) + read_mailmap_file(&mailmap, mailmap_file, 0); for (i = 0; i < argc; ++i) check_mailmap(&mailmap, argv[i]); diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index 5eb6bdc3f6..cef1ffe3ce 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -1,7 +1,6 @@ /* * GIT - The information manager from hell */ - #include "builtin.h" #include "refs.h" #include "setup.h" @@ -43,7 +42,7 @@ static int check_ref_format_branch(const char *arg) int nongit; setup_git_directory_gently(&nongit); - if (strbuf_check_branch_ref(&sb, arg) || + if (check_branch_ref(&sb, arg) || !skip_prefix(sb.buf, "refs/heads/", &name)) die("'%s' is not a valid branch name", arg); printf("%s\n", name); @@ -51,7 +50,10 @@ static int check_ref_format_branch(const char *arg) return 0; } -int cmd_check_ref_format(int argc, const char **argv, const char *prefix) +int cmd_check_ref_format(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; int normalize = 0; diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c index 6b62b5375b..ff6cdccc21 100644 --- a/builtin/checkout--worker.c +++ b/builtin/checkout--worker.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "entry.h" @@ -113,7 +114,10 @@ static const char * const checkout_worker_usage[] = { NULL }; -int cmd_checkout__worker(int argc, const char **argv, const char *prefix) +int cmd_checkout__worker(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout state = CHECKOUT_INIT; struct option checkout_worker_options[] = { diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 29e744d11b..6dd38eb05d 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -4,13 +4,12 @@ * Copyright (C) 2005 Linus Torvalds * */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "lockfile.h" #include "quote.h" -#include "repository.h" #include "cache-tree.h" #include "parse-options.h" #include "entry.h" @@ -208,7 +207,10 @@ static int option_parse_stage(const struct option *opt, return 0; } -int cmd_checkout_index(int argc, const char **argv, const char *prefix) +int cmd_checkout_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct lock_file lock_file = LOCK_INIT; diff --git a/builtin/checkout.c b/builtin/checkout.c index 3cf44b4683..5e5afa0f26 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "branch.h" @@ -23,6 +24,7 @@ #include "read-cache.h" #include "refs.h" #include "remote.h" +#include "repo-settings.h" #include "resolve-undo.h" #include "revision.h" #include "setup.h" @@ -125,7 +127,7 @@ static void branch_info_release(struct branch_info *info) static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit, int changed) { - return run_hooks_l("post-checkout", + return run_hooks_l(the_repository, "post-checkout", oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()), oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()), changed ? "1" : "0", NULL); @@ -740,7 +742,7 @@ static void setup_branch_path(struct branch_info *branch) &branch->oid, &branch->refname, 0)) repo_get_oid_committish(the_repository, branch->name, &branch->oid); - strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL); + copy_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL); if (strcmp(buf.buf, branch->name)) { free(branch->name); branch->name = xstrdup(buf.buf); @@ -884,7 +886,7 @@ static int merge_working_tree(const struct checkout_opts *opts, add_files_to_cache(the_repository, NULL, NULL, NULL, 0, 0); - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.verbosity = 0; work = write_in_core_index_as_tree(the_repository); @@ -950,11 +952,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts, const char *old_desc, *reflog_msg; if (opts->new_branch) { if (opts->new_orphan_branch) { + enum log_refs_config log_all_ref_updates = + repo_settings_get_log_all_ref_updates(the_repository); char *refname; refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); if (opts->new_branch_log && - !should_autocreate_reflog(refname)) { + !should_autocreate_reflog(log_all_ref_updates, refname)) { int ret; struct strbuf err = STRBUF_INIT; @@ -1045,7 +1049,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, report_tracking(new_branch_info); } -static int add_pending_uninteresting_ref(const char *refname, +static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -1572,6 +1576,10 @@ static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts, static int checkout_branch(struct checkout_opts *opts, struct branch_info *new_branch_info) { + int noop_switch = (!new_branch_info->name && + !opts->new_branch && + !opts->force_detach); + if (opts->pathspec.nr) die(_("paths cannot be used with switching branches")); @@ -1583,9 +1591,14 @@ static int checkout_branch(struct checkout_opts *opts, die(_("'%s' cannot be used with switching branches"), "--[no]-overlay"); - if (opts->writeout_stage) - die(_("'%s' cannot be used with switching branches"), - "--ours/--theirs"); + if (opts->writeout_stage) { + const char *msg; + if (noop_switch) + msg = _("'%s' needs the paths to check out"); + else + msg = _("'%s' cannot be used with switching branches"); + die(msg, "--ours/--theirs"); + } if (opts->force && opts->merge) die(_("'%s' cannot be used with '%s'"), "-f", "-m"); @@ -1612,10 +1625,8 @@ static int checkout_branch(struct checkout_opts *opts, die(_("Cannot switch branch to a non-commit '%s'"), new_branch_info->name); - if (!opts->switch_branch_doing_nothing_is_ok && - !new_branch_info->name && - !opts->new_branch && - !opts->force_detach) + if (noop_switch && + !opts->switch_branch_doing_nothing_is_ok) die(_("missing branch or commit argument")); if (!opts->implicit_detach && @@ -1705,7 +1716,7 @@ static struct option *add_common_switch_branch_options( N_("update ignored files (default)"), PARSE_OPT_NOCOMPLETE), OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees, - N_("do not check if another worktree is holding the given ref")), + N_("do not check if another worktree is using this branch")), OPT_END() }; struct option *newopts = parse_options_concat(prevopts, options); @@ -1946,7 +1957,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix, return ret; } -int cmd_checkout(int argc, const char **argv, const char *prefix) +int cmd_checkout(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; @@ -1993,7 +2007,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) checkout_usage); } -int cmd_switch(int argc, const char **argv, const char *prefix) +int cmd_switch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options = NULL; @@ -2029,7 +2046,10 @@ int cmd_switch(int argc, const char **argv, const char *prefix) switch_branch_usage); } -int cmd_restore(int argc, const char **argv, const char *prefix) +int cmd_restore(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; diff --git a/builtin/clean.c b/builtin/clean.c index ded5a91534..9c48dd0271 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -5,7 +5,7 @@ * * Based on git-clean.sh by Pavel Roskin */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -14,7 +14,6 @@ #include "parse-options.h" #include "path.h" #include "read-cache-ll.h" -#include "repository.h" #include "setup.h" #include "string-list.h" #include "quote.h" @@ -915,7 +914,10 @@ static void correct_untracked_entries(struct dir_struct *dir) dir->nr = dst; } -int cmd_clean(int argc, const char **argv, const char *prefix) +int cmd_clean(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, res; int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0; diff --git a/builtin/clone.c b/builtin/clone.c index af6017d41a..21721db28a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -7,8 +7,9 @@ * * Clone a repository into a different directory that does not yet exist. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "advice.h" #include "config.h" @@ -146,8 +147,8 @@ static struct option builtin_clone_options[] = { N_("create a shallow clone of that depth")), OPT_STRING(0, "shallow-since", &option_since, N_("time"), N_("create a shallow clone since a specific time")), - OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"), - N_("deepen history of shallow clone, excluding rev")), + OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"), + N_("deepen history of shallow clone, excluding ref")), OPT_BOOL(0, "single-branch", &option_single_branch, N_("clone only one branch, HEAD or --branch")), OPT_BOOL(0, "no-tags", &option_no_tags, @@ -573,7 +574,7 @@ static void write_remote_refs(const struct ref *local_refs) struct strbuf err = STRBUF_INIT; t = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + REF_TRANSACTION_FLAG_INITIAL, &err); if (!t) die("%s", err.buf); @@ -585,7 +586,7 @@ static void write_remote_refs(const struct ref *local_refs) die("%s", err.buf); } - if (initial_ref_transaction_commit(t, &err)) + if (ref_transaction_commit(t, &err)) die("%s", err.buf); strbuf_release(&err); @@ -729,7 +730,8 @@ static int git_sparse_checkout_init(const char *repo) return result; } -static int checkout(int submodule_progress, int filter_submodules) +static int checkout(int submodule_progress, int filter_submodules, + enum ref_storage_format ref_storage_format) { struct object_id oid; char *head; @@ -788,7 +790,7 @@ static int checkout(int submodule_progress, int filter_submodules) if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); - err |= run_hooks_l("post-checkout", oid_to_hex(null_oid()), + err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid()), oid_to_hex(&oid), "1", NULL); if (!err && (option_recurse_submodules.nr > 0)) { @@ -813,6 +815,10 @@ static int checkout(int submodule_progress, int filter_submodules) strvec_push(&cmd.args, "--no-fetch"); } + if (ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&cmd.args, "--ref-format=%s", + ref_storage_format_to_name(ref_storage_format)); + if (filter_submodules && filter_options.choice) strvec_pushf(&cmd.args, "--filter=%s", expand_list_objects_filter_spec(&filter_options)); @@ -951,7 +957,10 @@ static int path_exists(const char *path) return !stat(path, &sb); } -int cmd_clone(int argc, const char **argv, const char *prefix) +int cmd_clone(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { int is_bundle = 0, is_local; int reject_shallow = 0; @@ -1394,8 +1403,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix) * data from the --bundle-uri option. */ if (bundle_uri) { + struct remote_state *state; int has_heuristic = 0; + /* + * We need to save the remote state as our remote's lifetime is + * tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); @@ -1404,6 +1422,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) bundle_uri); else if (has_heuristic) git_config_set_gently("fetch.bundleuri", bundle_uri); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { /* * Populate transport->got_remote_bundle_uri and @@ -1413,12 +1435,26 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (transport->bundles && hashmap_get_size(&transport->bundles->bundles)) { + struct remote_state *state; + + /* + * We need to save the remote state as our remote's + * lifetime is tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); else if (fetch_bundle_list(the_repository, transport->bundles)) warning(_("failed to fetch advertised bundles")); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { clear_bundle_list(transport->bundles); FREE_AND_NULL(transport->bundles); @@ -1536,7 +1572,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) return 1; junk_mode = JUNK_LEAVE_REPO; - err = checkout(submodule_progress, filter_submodules); + err = checkout(submodule_progress, filter_submodules, + ref_storage_format); free(remote_name); strbuf_release(&reflog_msg); @@ -1549,7 +1586,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) free(dir); free(path); free(repo_to_free); - UNLEAK(repo); junk_mode = JUNK_LEAVE_ALL; transport_ls_refs_options_release(&transport_ls_refs_options); diff --git a/builtin/column.c b/builtin/column.c index 10ff7e0166..50314cc255 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -18,7 +19,10 @@ static int column_config(const char *var, const char *value, return git_column_config(var, value, cb, &colopts); } -int cmd_column(int argc, const char **argv, const char *prefix) +int cmd_column(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct string_list list = STRING_LIST_INIT_DUP; struct strbuf sb = STRBUF_INIT; diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 7102ee90a0..bd70d052e7 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -1,11 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "parse-options.h" -#include "repository.h" #include "commit-graph.h" #include "object-store-ll.h" #include "progress.h" @@ -63,7 +62,8 @@ static struct option *add_common_options(struct option *to) return parse_options_concat(common_opts, to); } -static int graph_verify(int argc, const char **argv, const char *prefix) +static int graph_verify(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct commit_graph *graph = NULL; struct object_directory *odb = NULL; @@ -95,7 +95,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix) usage_with_options(builtin_commit_graph_verify_usage, options); if (!opts.obj_dir) - opts.obj_dir = get_object_directory(); + opts.obj_dir = repo_get_object_directory(the_repository); if (opts.shallow) flags |= COMMIT_GRAPH_VERIFY_SHALLOW; if (opts.progress) @@ -215,7 +215,8 @@ static int git_commit_graph_write_config(const char *var, const char *value, return 0; } -static int graph_write(int argc, const char **argv, const char *prefix) +static int graph_write(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct string_list pack_indexes = STRING_LIST_INIT_DUP; struct strbuf buf = STRBUF_INIT; @@ -275,7 +276,7 @@ static int graph_write(int argc, const char **argv, const char *prefix) if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1) die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs")); if (!opts.obj_dir) - opts.obj_dir = get_object_directory(); + opts.obj_dir = repo_get_object_directory(the_repository); if (opts.append) flags |= COMMIT_GRAPH_WRITE_APPEND; if (opts.split) @@ -331,7 +332,10 @@ cleanup: return result; } -int cmd_commit_graph(int argc, const char **argv, const char *prefix) +int cmd_commit_graph(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_commit_graph_options[] = { @@ -350,5 +354,5 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) builtin_commit_graph_usage, 0); FREE_AND_NULL(options); - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 84bb450222..2ca1a57ebb 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -3,13 +3,14 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "object-name.h" #include "object-store-ll.h" -#include "repository.h" + #include "commit.h" #include "parse-options.h" @@ -90,7 +91,10 @@ static int parse_file_arg_callback(const struct option *opt, return 0; } -int cmd_commit_tree(int argc, const char **argv, const char *prefix) +int cmd_commit_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct strbuf buffer = STRBUF_INIT; struct commit_list *parents = NULL; diff --git a/builtin/commit.c b/builtin/commit.c index dec78dfb86..71d674138c 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -4,7 +4,7 @@ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com> * Based on git-commit.sh by Junio C Hamano and Linus Torvalds */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -26,6 +26,7 @@ #include "path.h" #include "preload-index.h" #include "read-cache.h" +#include "repository.h" #include "string-list.h" #include "rerere.h" #include "unpack-trees.h" @@ -41,7 +42,7 @@ static const char * const builtin_commit_usage[] = { N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" - " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>)]\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" @@ -134,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT; * is specified explicitly. */ static enum commit_msg_cleanup_mode cleanup_mode; -static char *cleanup_arg; +static char *cleanup_config; static enum commit_whence whence; static int use_editor = 1, include_status = 1; @@ -395,7 +396,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT)); setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1); - if (interactive_add(argv, prefix, patch_interactive) != 0) + if (interactive_add(the_repository, argv, prefix, patch_interactive) != 0) die(_("interactive add failed")); the_repository->index_file = old_repo_index_file; @@ -407,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix, discard_index(the_repository->index); read_index_from(the_repository->index, get_lock_file_path(&index_lock), - get_git_dir()); + repo_get_git_dir(the_repository)); if (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) { if (reopen_lock_file(&index_lock) < 0) die(_("unable to write index file")); @@ -472,7 +473,7 @@ static const char *prepare_index(const char **argv, const char *prefix, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write new index file")); commit_style = COMMIT_AS_IS; - ret = get_index_file(); + ret = repo_get_index_file(the_repository); goto out; } @@ -534,7 +535,7 @@ static const char *prepare_index(const char **argv, const char *prefix, discard_index(the_repository->index); ret = get_lock_file_path(&false_lock); - read_index_from(the_repository->index, ret, get_git_dir()); + read_index_from(the_repository->index, ret, repo_get_git_dir(the_repository)); out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); @@ -684,7 +685,9 @@ static void adjust_comment_line_char(const struct strbuf *sb) const char *p; if (!memchr(sb->buf, candidates[0], sb->len)) { - comment_line_str = xstrfmt("%c", candidates[0]); + free(comment_line_str_to_free); + comment_line_str = comment_line_str_to_free = + xstrfmt("%c", candidates[0]); return; } @@ -705,7 +708,8 @@ static void adjust_comment_line_char(const struct strbuf *sb) if (!*p) die(_("unable to select a comment character that is not used\n" "in the current commit message")); - comment_line_str = xstrfmt("%c", *p); + free(comment_line_str_to_free); + comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p); } static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, @@ -724,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, repo_unuse_commit_buffer(the_repository, commit, buffer); } +static void change_data_free(void *util, const char *str UNUSED) +{ + struct wt_status_change_data *d = util; + free(d->rename_source); + free(d); +} + static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *current_head, struct wt_status *s, @@ -987,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->use_color = 0; committable = run_status(s->fp, index_file, prefix, 1, s); s->use_color = saved_color_setting; - string_list_clear(&s->change, 1); + string_list_clear_func(&s->change, change_data_free); } else { struct object_id oid; const char *parent = "HEAD"; @@ -1069,7 +1080,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, */ discard_index(the_repository->index); } - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository)); if (cache_tree_update(the_repository->index, 0)) { error(_("Error building trees")); @@ -1376,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[], if (0 <= edit_flag) use_editor = edit_flag; - cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor); - handle_untracked_files_arg(s); if (all && argc > 0) @@ -1499,7 +1508,10 @@ static int git_status_config(const char *k, const char *v, return git_diff_ui_config(k, v, ctx, NULL); } -int cmd_status(int argc, const char **argv, const char *prefix) +int cmd_status(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { static int no_renames = -1; static const char *rename_score_arg = (const char *)-1; @@ -1622,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v, include_status = git_config_bool(k, v); return 0; } - if (!strcmp(k, "commit.cleanup")) - return git_config_string(&cleanup_arg, k, v); + if (!strcmp(k, "commit.cleanup")) { + FREE_AND_NULL(cleanup_config); + return git_config_string(&cleanup_config, k, v); + } if (!strcmp(k, "commit.gpgsign")) { sign_commit = git_config_bool(k, v) ? "" : NULL; return 0; @@ -1638,9 +1652,13 @@ static int git_commit_config(const char *k, const char *v, return git_status_config(k, v, ctx, s); } -int cmd_commit(int argc, const char **argv, const char *prefix) +int cmd_commit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct wt_status s; + static const char *cleanup_arg = NULL; static struct option builtin_commit_options[] = { OPT__QUIET(&quiet, N_("suppress summary after successful commit")), OPT__VERBOSE(&verbose, N_("show diff in commit message template")), @@ -1740,6 +1758,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (verbose == -1) verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose; + if (cleanup_arg) { + free(cleanup_config); + cleanup_config = xstrdup(cleanup_arg); + } + cleanup_mode = get_cleanup_mode(cleanup_config, use_editor); + if (dry_run) return dry_run_commit(argv, prefix, current_head, &s); index_file = prepare_index(argv, prefix, current_head, 0); @@ -1870,8 +1894,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), NULL, "post-commit", - NULL); + run_commit_hook(use_editor, repo_get_index_file(the_repository), + NULL, "post-commit", NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } diff --git a/builtin/config.c b/builtin/config.c index 20a0b64090..16e6e30555 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" #include "color.h" #include "editor.h" #include "environment.h" -#include "repository.h" #include "gettext.h" #include "ident.h" #include "parse-options.h" @@ -17,9 +17,9 @@ static const char *const builtin_config_usage[] = { N_("git config list [<file-option>] [<display-option>] [--includes]"), - N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"), + N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"), N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), N_("git config rename-section [<file-option>] <old-name> <new-name>"), N_("git config remove-section [<file-option>] <name>"), N_("git config edit [<file-option>]"), @@ -43,7 +43,7 @@ static const char *const builtin_config_set_usage[] = { }; static const char *const builtin_config_unset_usage[] = { - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), NULL }; @@ -807,8 +807,8 @@ static void location_options_init(struct config_location_options *opts, else opts->options.respect_includes = opts->respect_includes_opt; if (startup_info->have_repository) { - opts->options.commondir = get_git_common_dir(); - opts->options.git_dir = get_git_dir(); + opts->options.commondir = repo_get_common_dir(the_repository); + opts->options.git_dir = repo_get_git_dir(the_repository); } } @@ -826,7 +826,8 @@ static void display_options_init(struct config_display_options *opts) } } -static int cmd_config_list(int argc, const char **argv, const char *prefix) +static int cmd_config_list(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; struct config_display_options display_opts = CONFIG_DISPLAY_OPTIONS_INIT; @@ -861,7 +862,8 @@ static int cmd_config_list(int argc, const char **argv, const char *prefix) return 0; } -static int cmd_config_get(int argc, const char **argv, const char *prefix) +static int cmd_config_get(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; struct config_display_options display_opts = CONFIG_DISPLAY_OPTIONS_INIT; @@ -915,7 +917,8 @@ static int cmd_config_get(int argc, const char **argv, const char *prefix) return ret; } -static int cmd_config_set(int argc, const char **argv, const char *prefix) +static int cmd_config_set(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; const char *value_pattern = NULL, *comment_arg = NULL; @@ -973,7 +976,8 @@ static int cmd_config_set(int argc, const char **argv, const char *prefix) return ret; } -static int cmd_config_unset(int argc, const char **argv, const char *prefix) +static int cmd_config_unset(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; const char *value_pattern = NULL; @@ -1010,7 +1014,8 @@ static int cmd_config_unset(int argc, const char **argv, const char *prefix) return ret; } -static int cmd_config_rename_section(int argc, const char **argv, const char *prefix) +static int cmd_config_rename_section(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; struct option opts[] = { @@ -1026,8 +1031,8 @@ static int cmd_config_rename_section(int argc, const char **argv, const char *pr location_options_init(&location_opts, prefix); check_write(&location_opts.source); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], argv[1]); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], argv[1]); if (ret < 0) goto out; else if (!ret) @@ -1039,7 +1044,8 @@ out: return ret; } -static int cmd_config_remove_section(int argc, const char **argv, const char *prefix) +static int cmd_config_remove_section(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; struct option opts[] = { @@ -1055,8 +1061,8 @@ static int cmd_config_remove_section(int argc, const char **argv, const char *pr location_options_init(&location_opts, prefix); check_write(&location_opts.source); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], NULL); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], NULL); if (ret < 0) goto out; else if (!ret) @@ -1099,7 +1105,8 @@ static int show_editor(struct config_location_options *opts) return 0; } -static int cmd_config_edit(int argc, const char **argv, const char *prefix) +static int cmd_config_edit(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT; struct option opts[] = { @@ -1353,8 +1360,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix) else if (actions == ACTION_RENAME_SECTION) { check_write(&location_opts.source); check_argc(argc, 2, 2); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], argv[1]); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], argv[1]); if (ret < 0) goto out; else if (!ret) @@ -1365,8 +1372,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix) else if (actions == ACTION_REMOVE_SECTION) { check_write(&location_opts.source); check_argc(argc, 1, 1); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], NULL); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], NULL); if (ret < 0) goto out; else if (!ret) @@ -1392,7 +1399,10 @@ out: return ret; } -int cmd_config(int argc, const char **argv, const char *prefix) +int cmd_config(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *subcommand = NULL; struct option subcommand_opts[] = { @@ -1419,7 +1429,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (subcommand) { argc = parse_options(argc, argv, prefix, subcommand_opts, builtin_config_usage, PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_KEEP_UNKNOWN_OPT); - return subcommand(argc, argv, prefix); + return subcommand(argc, argv, prefix, repo); } return cmd_config_actions(argc, argv, prefix); diff --git a/builtin/count-objects.c b/builtin/count-objects.c index 2d4bb5e8d0..1e89148ed7 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -3,14 +3,12 @@ * * Copyright (c) 2006 Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" -#include "environment.h" #include "gettext.h" #include "path.h" -#include "repository.h" #include "parse-options.h" #include "quote.h" #include "packfile.h" @@ -69,7 +67,7 @@ static int count_loose(const struct object_id *oid, const char *path, else { loose_size += on_disk_bytes(st); loose++; - if (verbose && has_object_pack(oid)) + if (verbose && has_object_pack(the_repository, oid)) packed_loose++; } return 0; @@ -95,7 +93,10 @@ static char const * const count_objects_usage[] = { NULL }; -int cmd_count_objects(int argc, const char **argv, const char *prefix) +int cmd_count_objects(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int human_readable = 0; struct option opts[] = { @@ -113,10 +114,10 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) usage_with_options(count_objects_usage, opts); if (verbose) { report_garbage = real_report_garbage; - report_linked_checkout_garbage(); + report_linked_checkout_garbage(the_repository); } - for_each_loose_file_in_objdir(get_object_directory(), + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), count_loose, count_cruft, NULL, NULL); if (verbose) { diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index 4952b22547..bc22f5c6d2 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" @@ -287,7 +288,10 @@ static void init_socket_directory(const char *path) free(path_copy); } -int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) +int cmd_credential_cache_daemon(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct tempfile *socket_file; const char *socket_path; @@ -330,7 +334,10 @@ int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) #else -int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) +int cmd_credential_cache_daemon(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { const char * const usage[] = { "git credential-cache--daemon [--debug] <socket-path>", diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c index aaf2f8438b..7f733cb756 100644 --- a/builtin/credential-cache.c +++ b/builtin/credential-cache.c @@ -30,7 +30,7 @@ static int connection_fatally_broken(int error) static int connection_closed(int error) { - return (error == ECONNRESET); + return error == ECONNRESET || error == ECONNABORTED; } static int connection_fatally_broken(int error) @@ -137,7 +137,10 @@ static void announce_capabilities(void) credential_announce_capabilities(&c, stdout); } -int cmd_credential_cache(int argc, const char **argv, const char *prefix) +int cmd_credential_cache(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *socket_path_arg = NULL; char *socket_path; @@ -186,7 +189,8 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix) #else -int cmd_credential_cache(int argc, const char **argv, const char *prefix) +int cmd_credential_cache(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { const char * const usage[] = { "git credential-cache [options] <action>", diff --git a/builtin/credential-store.c b/builtin/credential-store.c index 97968bfa1c..e669e99dbf 100644 --- a/builtin/credential-store.c +++ b/builtin/credential-store.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -170,7 +171,10 @@ static void lookup_credential(const struct string_list *fns, struct credential * return; /* Found credential */ } -int cmd_credential_store(int argc, const char **argv, const char *prefix) +int cmd_credential_store(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char * const usage[] = { "git credential-store [<options>] <action>", diff --git a/builtin/credential.c b/builtin/credential.c index b72e76dd9a..14c8c6608b 100644 --- a/builtin/credential.c +++ b/builtin/credential.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "credential.h" #include "builtin.h" @@ -6,7 +8,10 @@ static const char usage_msg[] = "git credential (fill|approve|reject)"; -int cmd_credential(int argc, const char **argv, const char *prefix UNUSED) +int cmd_credential(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { const char *op; struct credential c = CREDENTIAL_INIT; diff --git a/builtin/describe.c b/builtin/describe.c index 954929c514..a6ef8af32a 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -149,7 +150,7 @@ static void add_to_known_names(const char *path, } } -static int get_name(const char *path, const struct object_id *oid, +static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { int is_tag = 0; @@ -365,6 +366,13 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) struct commit_name **slot; seen_commits++; + + if (match_cnt == max_candidates || + match_cnt == hashmap_get_size(&names)) { + gave_up_on = c; + break; + } + slot = commit_names_peek(&commit_names, c); n = slot ? *slot : NULL; if (n) { @@ -380,10 +388,6 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) if (n->prio == 2) annotated_cnt++; } - else { - gave_up_on = c; - break; - } } for (cur_match = 0; cur_match < match_cnt; cur_match++) { struct possible_tag *t = &all_matches[cur_match]; @@ -469,9 +473,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) fprintf(stderr, _("traversed %lu commits\n"), seen_commits); if (gave_up_on) { fprintf(stderr, - _("more than %i tags found; listed %i most recent\n" - "gave up search at %s\n"), - max_candidates, max_candidates, + _("found %i tags; gave up search at %s\n"), + max_candidates, oid_to_hex(&gave_up_on->object.oid)); } } @@ -571,7 +574,10 @@ static int option_parse_exact_match(const struct option *opt, const char *arg, return 0; } -int cmd_describe(int argc, const char **argv, const char *prefix) +int cmd_describe(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED ) { int contains = 0; struct option options[] = { @@ -650,7 +656,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) argv_copy[i] = args.v[i]; argv_copy[args.nr] = NULL; - ret = cmd_name_rev(args.nr, argv_copy, prefix); + ret = cmd_name_rev(args.nr, argv_copy, prefix, the_repository); strvec_clear(&args); free(argv_copy); @@ -716,7 +722,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) BUG("malformed internal diff-index command line"); run_diff_index(&revs, 0); - if (!diff_result_code(&revs.diffopt)) + if (!diff_result_code(&revs)) suffix = NULL; else suffix = dirty; diff --git a/builtin/diagnose.c b/builtin/diagnose.c index 4857a4395b..66a22d918e 100644 --- a/builtin/diagnose.c +++ b/builtin/diagnose.c @@ -11,7 +11,10 @@ static const char * const diagnose_usage[] = { NULL }; -int cmd_diagnose(int argc, const char **argv, const char *prefix) +int cmd_diagnose(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf zip_path = STRBUF_INIT; time_t now = time(NULL); diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 018011f29e..e0e0ccec23 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -3,13 +3,13 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" #include "preload-index.h" -#include "repository.h" #include "revision.h" static const char diff_files_usage[] = @@ -17,7 +17,10 @@ static const char diff_files_usage[] = "\n" COMMON_DIFF_OPTIONS_HELP; -int cmd_diff_files(int argc, const char **argv, const char *prefix) +int cmd_diff_files(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info rev; int result; @@ -82,7 +85,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) die_errno("repo_read_index_preload"); run_diff_files(&rev, options); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); release_revisions(&rev); return result; } diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 3e05260ac0..ad503624c0 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" #include "preload-index.h" -#include "repository.h" #include "revision.h" #include "setup.h" @@ -14,7 +14,10 @@ static const char diff_cache_usage[] = "\n" COMMON_DIFF_OPTIONS_HELP; -int cmd_diff_index(int argc, const char **argv, const char *prefix) +int cmd_diff_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info rev; unsigned int option = 0; @@ -25,6 +28,10 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) usage(diff_cache_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ + + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + repo_init_revisions(the_repository, &rev, prefix); rev.abbrev = 0; prefix = precompose_argv_prefix(argc, argv, prefix); @@ -71,7 +78,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) return -1; } run_diff_index(&rev, option); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); release_revisions(&rev); return result; } diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 0d3c611aac..4b6656bb9f 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" @@ -6,8 +7,8 @@ #include "hex.h" #include "log-tree.h" #include "read-cache-ll.h" -#include "repository.h" #include "revision.h" +#include "tmp-objdir.h" #include "tree.h" static struct rev_info log_tree_opt; @@ -107,7 +108,10 @@ static void diff_tree_tweak_rev(struct rev_info *rev) } } -int cmd_diff_tree(int argc, const char **argv, const char *prefix) +int cmd_diff_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { char line[1000]; struct object *tree1, *tree2; @@ -230,5 +234,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) diff_free(&opt->diffopt); } - return diff_result_code(&opt->diffopt); + return diff_result_code(opt); } diff --git a/builtin/diff.c b/builtin/diff.c index 9b6cdabe15..2fe92f373e 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -3,7 +3,7 @@ * * Copyright (c) 2006 Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "ewah/ewok.h" @@ -388,7 +388,15 @@ static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym) sym->skip = map; } -int cmd_diff(int argc, const char **argv, const char *prefix) +static void symdiff_release(struct symdiff *sdiff) +{ + bitmap_free(sdiff->skip); +} + +int cmd_diff(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct rev_info rev; @@ -614,11 +622,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix) builtin_diff_combined(&rev, argc, argv, ent.objects, ent.nr, first_non_parent); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); release_revisions(&rev); object_array_clear(&ent); - UNLEAK(blob); + symdiff_release(&sdiff); return result; } diff --git a/builtin/difftool.c b/builtin/difftool.c index dcc68e190c..40e971e225 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -11,8 +11,9 @@ * * Copyright (C) 2016 Johannes Schindelin */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "config.h" #include "copy.h" @@ -22,6 +23,7 @@ #include "hex.h" #include "parse-options.h" #include "read-cache-ll.h" +#include "repository.h" #include "sparse-index.h" #include "strvec.h" #include "strbuf.h" @@ -214,7 +216,7 @@ static void changed_files(struct hashmap *result, const char *index_path, struct child_process update_index = CHILD_PROCESS_INIT; struct child_process diff_files = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; - const char *git_dir = absolute_path(get_git_dir()); + const char *git_dir = absolute_path(repo_get_git_dir(the_repository)); FILE *fp; strvec_pushl(&update_index.args, @@ -338,7 +340,7 @@ static void write_file_in_directory(struct strbuf *dir, size_t dir_len, /* Write the file contents for the left and right sides of the difftool * dir-diff representation for submodules and symlinks. Symlinks and submodules * are written as regular text files so that external diff tools can diff them - * as text files, resulting in behavior that is analogous to to what "git diff" + * as text files, resulting in behavior that is analogous to what "git diff" * displays for symlink and submodule diffs. */ static void write_standin_files(struct pair_entry *entry, @@ -374,10 +376,11 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct checkout lstate, rstate; int err = 0; struct child_process cmd = CHILD_PROCESS_INIT; - struct hashmap wt_modified, tmp_modified; + struct hashmap wt_modified = HASHMAP_INIT(path_entry_cmp, NULL); + struct hashmap tmp_modified = HASHMAP_INIT(path_entry_cmp, NULL); int indices_loaded = 0; - workdir = get_git_work_tree(); + workdir = repo_get_work_tree(the_repository); /* Setup temp directories */ tmp = getenv("TMPDIR"); @@ -599,9 +602,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, * in the common case of --symlinks and the difftool updating * files through the symlink. */ - hashmap_init(&wt_modified, path_entry_cmp, NULL, wtindex.cache_nr); - hashmap_init(&tmp_modified, path_entry_cmp, NULL, wtindex.cache_nr); - for (i = 0; i < wtindex.cache_nr; i++) { struct hashmap_entry dummy; const char *name = wtindex.cache[i]->name; @@ -660,6 +660,12 @@ finish: if (fp) fclose(fp); + hashmap_clear_and_free(&working_tree_dups, struct working_tree_entry, entry); + hashmap_clear_and_free(&wt_modified, struct path_entry, entry); + hashmap_clear_and_free(&tmp_modified, struct path_entry, entry); + hashmap_clear_and_free(&submodules, struct pair_entry, entry); + hashmap_clear_and_free(&symlinks2, struct pair_entry, entry); + release_index(&wtindex); free(lbase_dir); free(rbase_dir); strbuf_release(&info); @@ -690,7 +696,10 @@ static int run_file_diff(int prompt, const char *prefix, return run_command(child); } -int cmd_difftool(int argc, const char **argv, const char *prefix) +int cmd_difftool(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0, tool_help = 0, no_index = 0; @@ -737,8 +746,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix) if (!no_index){ setup_work_tree(); - setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1); - setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1); + setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1); + setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1); } else if (dir_diff) die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index"); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 4b6e8c6832..e17f262e8e 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -3,6 +3,7 @@ * * Copyright (C) 2007 Johannes E. Schindelin */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -42,8 +43,8 @@ static int full_tree; static int reference_excluded_commits; static int show_original_ids; static int mark_tags; -static struct string_list extra_refs = STRING_LIST_INIT_NODUP; -static struct string_list tag_refs = STRING_LIST_INIT_NODUP; +static struct string_list extra_refs = STRING_LIST_INIT_DUP; +static struct string_list tag_refs = STRING_LIST_INIT_DUP; static struct refspec refspecs = REFSPEC_INIT_FETCH; static int anonymize; static struct hashmap anonymized_seeds; @@ -901,7 +902,7 @@ static void handle_tag(const char *name, struct tag *tag) free(buf); } -static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name) +static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_name) { switch (e->item->type) { case OBJ_COMMIT: @@ -932,14 +933,16 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) struct rev_cmdline_entry *e = info->rev + i; struct object_id oid; struct commit *commit; - char *full_name; + char *full_name = NULL; if (e->flags & UNINTERESTING) continue; if (repo_dwim_ref(the_repository, e->name, strlen(e->name), - &oid, &full_name, 0) != 1) + &oid, &full_name, 0) != 1) { + free(full_name); continue; + } if (refspecs.nr) { char *private; @@ -955,6 +958,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) warning("%s: Unexpected object of type %s, skipping.", e->name, type_name(e->item->type)); + free(full_name); continue; } @@ -963,10 +967,12 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) break; case OBJ_BLOB: export_blob(&commit->object.oid); + free(full_name); continue; default: /* OBJ_TAG (nested tags) is already handled */ warning("Tag points to object of unexpected type %s, skipping.", type_name(commit->object.type)); + free(full_name); continue; } @@ -979,6 +985,8 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) if (!*revision_sources_at(&revision_sources, commit)) *revision_sources_at(&revision_sources, commit) = full_name; + else + free(full_name); } string_list_sort(&extra_refs); @@ -1173,7 +1181,10 @@ static int parse_opt_anonymize_map(const struct option *opt, return 0; } -int cmd_fast_export(int argc, const char **argv, const char *prefix) +int cmd_fast_export(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct commit *commit; @@ -1278,9 +1289,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) revs.diffopt.format_callback = show_filemodify; revs.diffopt.format_callback_data = &paths_of_changed_objects; revs.diffopt.flags.recursive = 1; + revs.diffopt.no_free = 1; while ((commit = get_revision(&revs))) handle_commit(commit, &revs, &paths_of_changed_objects); + revs.diffopt.no_free = 0; handle_tags_and_duplicates(&extra_refs); handle_tags_and_duplicates(&tag_refs); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index d21c4053a7..a67c1c4416 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "lockfile.h" #include "object.h" @@ -13,6 +13,7 @@ #include "delta.h" #include "pack.h" #include "path.h" +#include "read-cache-ll.h" #include "refs.h" #include "csum-file.h" #include "quote.h" @@ -179,6 +180,7 @@ static unsigned long branch_load_count; static int failure; static FILE *pack_edges; static unsigned int show_stats = 1; +static unsigned int quiet; static int global_argc; static const char **global_argv; static const char *global_prefix; @@ -206,8 +208,8 @@ static unsigned int object_entry_alloc = 5000; static struct object_entry_pool *blocks; static struct hashmap object_table; static struct mark_set *marks; -static const char *export_marks_file; -static const char *import_marks_file; +static char *export_marks_file; +static char *import_marks_file; static int import_marks_file_from_stream; static int import_marks_file_ignore_missing; static int import_marks_file_done; @@ -765,6 +767,7 @@ static void start_packfile(void) p->pack_fd = pack_fd; p->do_not_close = 1; + p->repo = the_repository; pack_file = hashfd(pack_fd, p->pack_name); pack_data = p; @@ -805,7 +808,7 @@ static char *keep_pack(const char *curr_index_name) struct strbuf name = STRBUF_INIT; int keep_fd; - odb_pack_name(&name, pack_data->hash, "keep"); + odb_pack_name(pack_data->repo, &name, pack_data->hash, "keep"); keep_fd = odb_pack_keep(name.buf); if (keep_fd < 0) die_errno("cannot create keep file"); @@ -813,11 +816,11 @@ static char *keep_pack(const char *curr_index_name) if (close(keep_fd)) die_errno("failed to write keep file"); - odb_pack_name(&name, pack_data->hash, "pack"); + odb_pack_name(pack_data->repo, &name, pack_data->hash, "pack"); if (finalize_object_file(pack_data->pack_name, name.buf)) die("cannot store pack file"); - odb_pack_name(&name, pack_data->hash, "idx"); + odb_pack_name(pack_data->repo, &name, pack_data->hash, "idx"); if (finalize_object_file(curr_index_name, name.buf)) die("cannot store index file"); free((void *)curr_index_name); @@ -831,7 +834,7 @@ static void unkeep_all_packs(void) for (k = 0; k < pack_id; k++) { struct packed_git *p = all_packs[k]; - odb_pack_name(&name, p->hash, "keep"); + odb_pack_name(p->repo, &name, p->hash, "keep"); unlink_or_warn(name.buf); } strbuf_release(&name); @@ -888,7 +891,7 @@ static void end_packfile(void) idx_name = keep_pack(create_index()); /* Register the packfile with core git's machinery. */ - new_p = add_packed_git(idx_name, strlen(idx_name), 1); + new_p = add_packed_git(pack_data->repo, idx_name, strlen(idx_name), 1); if (!new_p) die("core git rejected index %s", idx_name); all_packs[pack_id] = new_p; @@ -966,8 +969,7 @@ static int store_object( if (e->idx.offset) { duplicate_count_by_type[type]++; return 1; - } else if (find_sha1_pack(oid.hash, - get_all_packs(the_repository))) { + } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { e->type = type; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1167,8 +1169,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) duplicate_count_by_type[OBJ_BLOB]++; truncate_pack(&checkpoint); - } else if (find_sha1_pack(oid.hash, - get_all_packs(the_repository))) { + } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { e->type = OBJ_BLOB; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1604,7 +1605,19 @@ static int update_branch(struct branch *b) struct ref_transaction *transaction; struct object_id old_oid; struct strbuf err = STRBUF_INIT; - + static const char *replace_prefix = "refs/replace/"; + + if (starts_with(b->name, replace_prefix) && + !strcmp(b->name + strlen(replace_prefix), + oid_to_hex(&b->oid))) { + if (!quiet) + warning("Dropping %s since it would point to " + "itself (i.e. to %s)", + b->name, oid_to_hex(&b->oid)); + refs_delete_ref(get_main_ref_store(the_repository), + NULL, b->name, NULL, 0); + return 0; + } if (is_null_oid(&b->oid)) { if (b->delete) refs_delete_ref(get_main_ref_store(the_repository), @@ -1636,7 +1649,7 @@ static int update_branch(struct branch *b) } } transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction || ref_transaction_update(transaction, b->name, &b->oid, &old_oid, NULL, NULL, 0, msg, &err) || @@ -1671,7 +1684,7 @@ static void dump_tags(void) struct ref_transaction *transaction; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { failure |= error("%s", err.buf); goto cleanup; @@ -2414,6 +2427,9 @@ static void file_change_m(const char *p, struct branch *b) tree_content_replace(&b->branch_tree, &oid, mode, NULL); return; } + + if (!verify_path(path.buf, mode)) + die("invalid path '%s'", path.buf); tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL); } @@ -2451,6 +2467,8 @@ static void file_change_cr(const char *p, struct branch *b, int rename) leaf.tree); return; } + if (!verify_path(dest.buf, leaf.versions[1].mode)) + die("invalid path '%s'", dest.buf); tree_content_set(&b->branch_tree, dest.buf, &leaf.versions[1].oid, leaf.versions[1].mode, @@ -3274,6 +3292,7 @@ static void option_import_marks(const char *marks, read_marks(); } + free(import_marks_file); import_marks_file = make_fast_import_path(marks); import_marks_file_from_stream = from_stream; import_marks_file_ignore_missing = ignore_missing; @@ -3316,6 +3335,7 @@ static void option_active_branches(const char *branches) static void option_export_marks(const char *marks) { + free(export_marks_file); export_marks_file = make_fast_import_path(marks); } @@ -3357,6 +3377,8 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list) free(f); string_list_insert(list, s)->util = ms; + + free(s); } static int parse_one_option(const char *option) @@ -3386,6 +3408,7 @@ static int parse_one_option(const char *option) option_export_pack_edges(option); } else if (!strcmp(option, "quiet")) { show_stats = 0; + quiet = 1; } else if (!strcmp(option, "stats")) { show_stats = 1; } else if (!strcmp(option, "allow-unsafe-features")) { @@ -3481,8 +3504,8 @@ static void git_pack_config(void) if (!git_config_get_int("pack.indexversion", &indexversion_value)) { pack_idx_opts.version = indexversion_value; if (pack_idx_opts.version > 2) - git_die_config("pack.indexversion", - "bad pack.indexVersion=%"PRIu32, pack_idx_opts.version); + git_die_config(the_repository, "pack.indexversion", + "bad pack.indexVersion=%"PRIu32, pack_idx_opts.version); } if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value)) max_packsize = packsizelimit_value; @@ -3533,7 +3556,10 @@ static void parse_argv(void) build_mark_map(&sub_marks_from, &sub_marks_to); } -int cmd_fast_import(int argc, const char **argv, const char *prefix) +int cmd_fast_import(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { unsigned int i; @@ -3654,7 +3680,7 @@ int cmd_fast_import(int argc, const char **argv, const char *prefix) fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)((tree_entry_allocd + fi_mem_pool.pool_alloc) /1024)); fprintf(stderr, " objects: %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024); fprintf(stderr, "---------------------------------------------------------------------\n"); - pack_report(); + pack_report(repo); fprintf(stderr, "---------------------------------------------------------------------\n"); fprintf(stderr, "\n"); } diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index af329e8d5c..62e8c3aa6b 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -43,12 +44,16 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, (*sought)[*nr - 1] = ref; } -int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) +int cmd_fetch_pack(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i, ret; - struct ref *ref = NULL; + struct ref *fetched_refs = NULL, *remote_refs = NULL; const char *dest = NULL; struct ref **sought = NULL; + struct ref **sought_to_free = NULL; int nr_sought = 0, alloc_sought = 0; int fd[2]; struct string_list pack_lockfiles = STRING_LIST_INIT_DUP; @@ -228,19 +233,27 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) version = discover_version(&reader); switch (version) { case protocol_v2: - get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL, + get_remote_refs(fd[1], &reader, &remote_refs, 0, NULL, NULL, args.stateless_rpc); break; case protocol_v1: case protocol_v0: - get_remote_heads(&reader, &ref, 0, NULL, &shallow); + get_remote_heads(&reader, &remote_refs, 0, NULL, &shallow); break; case protocol_unknown_version: BUG("unknown protocol version"); } - ref = fetch_pack(&args, fd, ref, sought, nr_sought, + /* + * Create a shallow copy of `sought` so that we can free all of its entries. + * This is because `fetch_pack()` will modify the array to evict some + * entries, but won't free those. + */ + DUP_ARRAY(sought_to_free, sought, nr_sought); + + fetched_refs = fetch_pack(&args, fd, remote_refs, sought, nr_sought, &shallow, pack_lockfiles_ptr, version); + if (pack_lockfiles.nr) { int i; @@ -260,7 +273,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) if (finish_connect(conn)) return 1; - ret = !ref; + ret = !fetched_refs; /* * If the heads to pull were given, we should have consumed @@ -270,11 +283,18 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) */ ret |= report_unmatched_refs(sought, nr_sought); - while (ref) { + for (struct ref *ref = fetched_refs; ref; ref = ref->next) printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); - ref = ref->next; - } + for (size_t i = 0; i < nr_sought; i++) + free_one_ref(sought_to_free[i]); + free(sought_to_free); + free(sought); + free_refs(fetched_refs); + free_refs(remote_refs); + list_objects_filter_release(&args.filter_options); + oid_array_clear(&shallow); + string_list_clear(&pack_lockfiles, 0); return ret; } diff --git a/builtin/fetch.c b/builtin/fetch.c index 693f02b958..335083eb10 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1,13 +1,13 @@ /* * "git fetch" */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" #include "gettext.h" #include "environment.h" #include "hex.h" -#include "repository.h" #include "refs.h" #include "refspec.h" #include "object-name.h" @@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map, return ent; } -static int add_one_refname(const char *refname, +static int add_one_refname(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cbdata) { @@ -454,13 +454,10 @@ static void filter_prefetch_refspec(struct refspec *rs) ref_namespace[NAMESPACE_TAGS].ref))) { int j; - free(rs->items[i].src); - free(rs->items[i].dst); + refspec_item_clear(&rs->items[i]); - for (j = i + 1; j < rs->nr; j++) { + for (j = i + 1; j < rs->nr; j++) rs->items[j - 1] = rs->items[j]; - rs->raw[j - 1] = rs->raw[j]; - } rs->nr--; i--; continue; @@ -668,7 +665,7 @@ static int s_update_ref(const char *action, */ if (!transaction) { transaction = our_transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { ret = STORE_REF_ERROR_OTHER; goto out; @@ -1161,7 +1158,7 @@ static int store_updated_refs(struct display_state *display_state, opt.exclude_hidden_refs_section = "fetch"; rm = ref_map; if (check_connected(iterate_ref_map, &rm, &opt)) { - rc = error(_("%s did not send all necessary objects\n"), + rc = error(_("%s did not send all necessary objects"), display_state->url); goto abort; } @@ -1458,12 +1455,13 @@ static void set_option(struct transport *transport, const char *name, const char die(_("option \"%s\" value \"%s\" is not valid for %s"), name, value, transport->url); if (r > 0) - warning(_("option \"%s\" is ignored for %s\n"), + warning(_("option \"%s\" is ignored for %s"), name, transport->url); } static int add_oid(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -1669,7 +1667,7 @@ static int do_fetch(struct transport *transport, if (atomic_fetch) { transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { retcode = -1; goto cleanup; @@ -1730,11 +1728,8 @@ static int do_fetch(struct transport *transport, goto cleanup; retcode = ref_transaction_commit(transaction, &err); - if (retcode) { - ref_transaction_free(transaction); - transaction = NULL; + if (retcode) goto cleanup; - } } commit_fetch_head(&fetch_head); @@ -1802,8 +1797,11 @@ cleanup: if (transaction && ref_transaction_abort(transaction, &err) && err.len) error("%s", err.buf); + transaction = NULL; } + if (transaction) + ref_transaction_free(transaction); display_state_release(&display_state); close_fetch_head(&fetch_head); strbuf_release(&err); @@ -1979,6 +1977,8 @@ static int fetch_multiple(struct string_list *list, int max_children, strvec_pushl(&argv, "-c", "fetch.bundleURI=", "fetch", "--append", "--no-auto-gc", "--no-write-commit-graph", NULL); + for (i = 0; i < server_options.nr; i++) + strvec_pushf(&argv, "--server-option=%s", server_options.items[i].string); add_options_to_argv(&argv, config); if (max_children != 1 && list->nr != 1) { @@ -2137,7 +2137,10 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, return exit_code; } -int cmd_fetch(int argc, const char **argv, const char *prefix) +int cmd_fetch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct fetch_config config = { .display_format = DISPLAY_FORMAT_FULL, @@ -2209,8 +2212,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) N_("deepen history of shallow clone")), OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), N_("deepen history of shallow repository based on time")), - OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"), - N_("deepen history of shallow clone, excluding rev")), + OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("ref"), + N_("deepen history of shallow clone, excluding ref")), OPT_INTEGER(0, "deepen", &deepen_relative, N_("deepen history of shallow clone")), OPT_SET_INT_F(0, "unshallow", &unshallow, @@ -2407,6 +2410,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) struct oidset_iter iter; const struct object_id *oid; + trace2_region_enter("fetch", "negotiate-only", the_repository); if (!remote) die(_("must supply remote when using --negotiate-only")); gtransport = prepare_transport(remote, 1); @@ -2415,6 +2419,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } else { warning(_("protocol does not support --negotiate-only, exiting")); result = 1; + trace2_region_leave("fetch", "negotiate-only", the_repository); goto cleanup; } if (server_options.nr) @@ -2425,11 +2430,17 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) while ((oid = oidset_iter_next(&iter))) printf("%s\n", oid_to_hex(oid)); oidset_clear(&acked_commits); + trace2_region_leave("fetch", "negotiate-only", the_repository); } else if (remote) { - if (filter_options.choice || repo_has_promisor_remote(the_repository)) + if (filter_options.choice || repo_has_promisor_remote(the_repository)) { + trace2_region_enter("fetch", "setup-partial", the_repository); fetch_one_setup_partial(remote); + trace2_region_leave("fetch", "setup-partial", the_repository); + } + trace2_region_enter("fetch", "fetch-one", the_repository); result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs, &config); + trace2_region_leave("fetch", "fetch-one", the_repository); } else { int max_children = max_jobs; @@ -2449,7 +2460,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) max_children = config.parallel; /* TODO should this also die if we have a previous partial-clone? */ + trace2_region_enter("fetch", "fetch-multiple", the_repository); result = fetch_multiple(&list, max_children, &config); + trace2_region_leave("fetch", "fetch-multiple", the_repository); } /* @@ -2471,6 +2484,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) max_children = config.parallel; add_options_to_argv(&options, &config); + trace2_region_enter_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix); result = fetch_submodules(the_repository, &options, submodule_prefix, @@ -2478,6 +2492,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) recurse_submodules_default, verbosity < 0, max_children); + trace2_region_leave_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix); strvec_clear(&options); } @@ -2501,9 +2516,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (progress) commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS; + trace2_region_enter("fetch", "write-commit-graph", the_repository); write_commit_graph_reachable(the_repository->objects->odb, commit_graph_flags, NULL); + trace2_region_leave("fetch", "write-commit-graph", the_repository); } if (enable_auto_gc) { diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 957786d1b3..189cd1096a 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "fmt-merge-msg.h" @@ -9,7 +10,10 @@ static const char * const fmt_merge_msg_usage[] = { NULL }; -int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) +int cmd_fmt_merge_msg(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { char *inpath = NULL; const char *message = NULL; @@ -67,6 +71,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) return ret; write_in_full(STDOUT_FILENO, output.buf, output.len); + strbuf_release(&input); + strbuf_release(&output); free(inpath); return 0; } diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 5517a4a1c0..715745a262 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -16,7 +17,10 @@ static char const * const for_each_ref_usage[] = { NULL }; -int cmd_for_each_ref(int argc, const char **argv, const char *prefix) +int cmd_for_each_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -104,6 +108,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) filter_and_format_refs(&filter, flags, sorting, &format); ref_filter_clear(&filter); + ref_format_clear(&format); ref_sorting_release(sorting); strvec_clear(&vec); return 0; diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c index c4fa41fda9..fae7f91cf1 100644 --- a/builtin/for-each-repo.c +++ b/builtin/for-each-repo.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" #include "path.h" -#include "repository.h" #include "run-command.h" #include "string-list.h" @@ -29,7 +29,10 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv) return run_command(&child); } -int cmd_for_each_repo(int argc, const char **argv, const char *prefix) +int cmd_for_each_repo(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static const char *config_key = NULL; int keep_going = 0; diff --git a/builtin/fsck.c b/builtin/fsck.c index d13a226c2e..0196c54eb6 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "commit.h" #include "tree.h" @@ -89,13 +89,16 @@ static int objerror(struct object *obj, const char *err) return -1; } -static int fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id UNUSED, - const char *message) +static int fsck_objects_error_func(struct fsck_options *o UNUSED, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) { + struct fsck_object_report *report = fsck_report; + const struct object_id *oid = report->oid; + enum object_type object_type = report->object_type; + switch (msg_type) { case FSCK_WARN: /* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */ @@ -147,7 +150,7 @@ static int mark_object(struct object *obj, enum object_type type, return 0; obj->flags |= REACHABLE; - if (is_promisor_object(&obj->oid)) + if (is_promisor_object(the_repository, &obj->oid)) /* * Further recursion does not need to be performed on this * object since it is a promisor object (so it does not need to @@ -267,9 +270,9 @@ static void check_reachable_object(struct object *obj) * do a full fsck */ if (!(obj->flags & HAS_OBJ)) { - if (is_promisor_object(&obj->oid)) + if (is_promisor_object(the_repository, &obj->oid)) return; - if (has_object_pack(&obj->oid)) + if (has_object_pack(the_repository, &obj->oid)) return; /* it is in pack - forget about it */ printf_ln(_("missing %s %s"), printable_type(&obj->oid, obj->type), @@ -388,7 +391,10 @@ static void check_connectivity(void) * traversal. */ for_each_loose_object(mark_loose_unreachable_referents, NULL, 0); - for_each_packed_object(mark_packed_unreachable_referents, NULL, 0); + for_each_packed_object(the_repository, + mark_packed_unreachable_referents, + NULL, + 0); } /* Look up all the requirements, warn about missing objects.. */ @@ -485,7 +491,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, refname, timestamp); obj->flags |= USED; mark_object_reachable(obj); - } else if (!is_promisor_object(oid)) { + } else if (!is_promisor_object(the_repository, oid)) { error(_("%s: invalid reflog entry %s"), refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; @@ -521,14 +527,14 @@ static int fsck_handle_reflog(const char *logname, void *cb_data) return 0; } -static int fsck_handle_ref(const char *refname, const struct object_id *oid, +static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object *obj; obj = parse_object(the_repository, oid); if (!obj) { - if (is_promisor_object(oid)) { + if (is_promisor_object(the_repository, oid)) { /* * Increment default_refs anyway, because this is a * valid ref. @@ -576,7 +582,7 @@ static void get_default_heads(void) strbuf_worktree_ref(wt, &ref, "HEAD"); fsck_head_link(ref.buf, &head_points_at, &head_oid); if (head_points_at && !is_null_oid(&head_oid)) - fsck_handle_ref(ref.buf, &head_oid, 0, NULL); + fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL); strbuf_release(&ref); if (include_reflogs) @@ -922,7 +928,10 @@ static struct option fsck_opts[] = { OPT_END(), }; -int cmd_fsck(int argc, const char **argv, const char *prefix) +int cmd_fsck(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct object_directory *odb; @@ -938,7 +947,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fsck_walk_options.walk = mark_object; fsck_obj_options.walk = mark_used; - fsck_obj_options.error_func = fsck_error_func; + fsck_obj_options.error_func = fsck_objects_error_func; if (check_strict) fsck_obj_options.strict = 1; @@ -960,7 +969,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); - for_each_packed_object(mark_packed_for_connectivity, NULL, 0); + for_each_packed_object(the_repository, + mark_packed_for_connectivity, NULL, 0); } else { prepare_alt_odb(the_repository); for (odb = the_repository->objects->odb; odb; odb = odb->next) @@ -1005,7 +1015,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) &oid); if (!obj || !(obj->flags & HAS_OBJ)) { - if (is_promisor_object(&oid)) + if (is_promisor_object(the_repository, &oid)) continue; error(_("%s: object missing"), oid_to_hex(&oid)); errors_found |= ERROR_OBJECT; @@ -1050,7 +1060,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) * and may get overwritten by other calls * while we're examining the index. */ - path = xstrdup(worktree_git_path(wt, "index")); + path = xstrdup(worktree_git_path(the_repository, wt, "index")); read_index_from(&istate, path, get_worktree_git_dir(wt)); fsck_index(&istate, path, wt->is_current); discard_index(&istate); diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 1593713f4c..f3f6bd330b 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" #include "dir.h" -#include "environment.h" #include "gettext.h" #include "parse-options.h" #include "fsmonitor-ll.h" @@ -11,7 +11,7 @@ #include "compat/fsmonitor/fsm-health.h" #include "compat/fsmonitor/fsm-listen.h" #include "fsmonitor--daemon.h" -#include "repository.h" + #include "simple-ipc.h" #include "khash.h" #include "run-command.h" @@ -1208,9 +1208,9 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state) * system event listener thread so that we have the IPC handle * before we need it. */ - if (ipc_server_run_async(&state->ipc_server_data, - state->path_ipc.buf, &ipc_opts, - handle_client, state)) + if (ipc_server_init_async(&state->ipc_server_data, + state->path_ipc.buf, &ipc_opts, + handle_client, state)) return error_errno( _("could not start IPC thread pool on '%s'"), state->path_ipc.buf); @@ -1291,7 +1291,8 @@ static int fsmonitor_run_daemon(void) /* Prepare to (recursively) watch the <worktree-root> directory. */ strbuf_init(&state.path_worktree_watch, 0); - strbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree())); + strbuf_addstr(&state.path_worktree_watch, + absolute_path(repo_get_work_tree(the_repository))); state.nr_paths_watching = 1; strbuf_init(&state.alias.alias, 0); @@ -1311,7 +1312,9 @@ static int fsmonitor_run_daemon(void) strbuf_addstr(&state.path_gitdir_watch, "/.git"); if (!is_directory(state.path_gitdir_watch.buf)) { strbuf_reset(&state.path_gitdir_watch); - strbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir())); + strbuf_addstr(&state.path_gitdir_watch, + absolute_path(repo_get_git_dir(the_repository))); + strbuf_strip_suffix(&state.path_gitdir_watch, "/."); state.nr_paths_watching = 2; } @@ -1521,7 +1524,10 @@ static int try_to_start_background_daemon(void) } } -int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) +int cmd_fsmonitor__daemon(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *subcmd; enum fsmonitor_reason reason; @@ -1584,7 +1590,7 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) } #else -int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED) +int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { struct option options[] = { OPT_END() diff --git a/builtin/gc.c b/builtin/gc.c index 72bac2554f..4ae5196aed 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -9,13 +9,12 @@ * * Copyright (c) 2006 Shawn O. Pearce */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "date.h" #include "environment.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "tempfile.h" #include "lockfile.h" @@ -49,23 +48,7 @@ static const char * const builtin_gc_usage[] = { NULL }; -static int pack_refs = 1; -static int prune_reflogs = 1; -static int cruft_packs = 1; -static unsigned long max_cruft_size; -static int aggressive_depth = 50; -static int aggressive_window = 250; -static int gc_auto_threshold = 6700; -static int gc_auto_pack_limit = 50; -static int detach_auto = 1; static timestamp_t gc_log_expire_time; -static const char *gc_log_expire = "1.day.ago"; -static const char *prune_expire = "2.weeks.ago"; -static const char *prune_worktrees_expire = "3.months.ago"; -static char *repack_filter; -static char *repack_filter_to; -static unsigned long big_pack_threshold; -static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE; static struct strvec reflog = STRVEC_INIT; static struct strvec repack = STRVEC_INIT; @@ -125,13 +108,6 @@ static void process_log_file_at_exit(void) process_log_file(); } -static void process_log_file_on_signal(int signo) -{ - process_log_file(); - sigchain_pop(signo); - raise(signo); -} - static int gc_config_is_timestamp_never(const char *var) { const char *value; @@ -145,37 +121,110 @@ static int gc_config_is_timestamp_never(const char *var) return 0; } -static void gc_config(void) +struct gc_config { + int pack_refs; + int prune_reflogs; + int cruft_packs; + unsigned long max_cruft_size; + int aggressive_depth; + int aggressive_window; + int gc_auto_threshold; + int gc_auto_pack_limit; + int detach_auto; + char *gc_log_expire; + char *prune_expire; + char *prune_worktrees_expire; + char *repack_filter; + char *repack_filter_to; + unsigned long big_pack_threshold; + unsigned long max_delta_cache_size; + /* + * Remove this member from gc_config once repo_settings is passed + * through the callchain. + */ + size_t delta_base_cache_limit; +}; + +#define GC_CONFIG_INIT { \ + .pack_refs = 1, \ + .prune_reflogs = 1, \ + .cruft_packs = 1, \ + .aggressive_depth = 50, \ + .aggressive_window = 250, \ + .gc_auto_threshold = 6700, \ + .gc_auto_pack_limit = 50, \ + .detach_auto = 1, \ + .gc_log_expire = xstrdup("1.day.ago"), \ + .prune_expire = xstrdup("2.weeks.ago"), \ + .prune_worktrees_expire = xstrdup("3.months.ago"), \ + .max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE, \ + .delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT, \ +} + +static void gc_config_release(struct gc_config *cfg) +{ + free(cfg->gc_log_expire); + free(cfg->prune_expire); + free(cfg->prune_worktrees_expire); + free(cfg->repack_filter); + free(cfg->repack_filter_to); +} + +static void gc_config(struct gc_config *cfg) { const char *value; + char *owned = NULL; + unsigned long ulongval; if (!git_config_get_value("gc.packrefs", &value)) { if (value && !strcmp(value, "notbare")) - pack_refs = -1; + cfg->pack_refs = -1; else - pack_refs = git_config_bool("gc.packrefs", value); + cfg->pack_refs = git_config_bool("gc.packrefs", value); } if (gc_config_is_timestamp_never("gc.reflogexpire") && gc_config_is_timestamp_never("gc.reflogexpireunreachable")) - prune_reflogs = 0; + cfg->prune_reflogs = 0; + + git_config_get_int("gc.aggressivewindow", &cfg->aggressive_window); + git_config_get_int("gc.aggressivedepth", &cfg->aggressive_depth); + git_config_get_int("gc.auto", &cfg->gc_auto_threshold); + git_config_get_int("gc.autopacklimit", &cfg->gc_auto_pack_limit); + git_config_get_bool("gc.autodetach", &cfg->detach_auto); + git_config_get_bool("gc.cruftpacks", &cfg->cruft_packs); + git_config_get_ulong("gc.maxcruftsize", &cfg->max_cruft_size); + + if (!repo_config_get_expiry(the_repository, "gc.pruneexpire", &owned)) { + free(cfg->prune_expire); + cfg->prune_expire = owned; + } - git_config_get_int("gc.aggressivewindow", &aggressive_window); - git_config_get_int("gc.aggressivedepth", &aggressive_depth); - git_config_get_int("gc.auto", &gc_auto_threshold); - git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); - git_config_get_bool("gc.autodetach", &detach_auto); - git_config_get_bool("gc.cruftpacks", &cruft_packs); - git_config_get_ulong("gc.maxcruftsize", &max_cruft_size); - git_config_get_expiry("gc.pruneexpire", &prune_expire); - git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire); - git_config_get_expiry("gc.logexpiry", &gc_log_expire); + if (!repo_config_get_expiry(the_repository, "gc.worktreepruneexpire", &owned)) { + free(cfg->prune_worktrees_expire); + cfg->prune_worktrees_expire = owned; + } - git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold); - git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size); + if (!repo_config_get_expiry(the_repository, "gc.logexpiry", &owned)) { + free(cfg->gc_log_expire); + cfg->gc_log_expire = owned; + } - git_config_get_string("gc.repackfilter", &repack_filter); - git_config_get_string("gc.repackfilterto", &repack_filter_to); + git_config_get_ulong("gc.bigpackthreshold", &cfg->big_pack_threshold); + git_config_get_ulong("pack.deltacachesize", &cfg->max_delta_cache_size); + + if (!git_config_get_ulong("core.deltabasecachelimit", &ulongval)) + cfg->delta_base_cache_limit = ulongval; + + if (!git_config_get_string("gc.repackfilter", &owned)) { + free(cfg->repack_filter); + cfg->repack_filter = owned; + } + + if (!git_config_get_string("gc.repackfilterto", &owned)) { + free(cfg->repack_filter_to); + cfg->repack_filter_to = owned; + } git_config(git_default_config, NULL); } @@ -202,11 +251,15 @@ static enum schedule_priority parse_schedule(const char *value) struct maintenance_run_opts { int auto_flag; + int detach; int quiet; enum schedule_priority schedule; }; +#define MAINTENANCE_RUN_OPTS_INIT { \ + .detach = -1, \ +} -static int pack_refs_condition(void) +static int pack_refs_condition(UNUSED struct gc_config *cfg) { /* * The auto-repacking logic for refs is handled by the ref backends and @@ -216,7 +269,8 @@ static int pack_refs_condition(void) return 1; } -static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts) +static int maintenance_task_pack_refs(struct maintenance_run_opts *opts, + UNUSED struct gc_config *cfg) { struct child_process cmd = CHILD_PROCESS_INIT; @@ -228,7 +282,7 @@ static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts * return run_command(&cmd); } -static int too_many_loose_objects(void) +static int too_many_loose_objects(struct gc_config *cfg) { /* * Quickly check if a "gc" is needed, by estimating how @@ -247,7 +301,7 @@ static int too_many_loose_objects(void) if (!dir) return 0; - auto_threshold = DIV_ROUND_UP(gc_auto_threshold, 256); + auto_threshold = DIV_ROUND_UP(cfg->gc_auto_threshold, 256); while ((ent = readdir(dir)) != NULL) { if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose || ent->d_name[hexsz_loose] != '\0') @@ -283,12 +337,12 @@ static struct packed_git *find_base_packs(struct string_list *packs, return base; } -static int too_many_packs(void) +static int too_many_packs(struct gc_config *cfg) { struct packed_git *p; int cnt; - if (gc_auto_pack_limit <= 0) + if (cfg->gc_auto_pack_limit <= 0) return 0; for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) { @@ -302,7 +356,7 @@ static int too_many_packs(void) */ cnt++; } - return gc_auto_pack_limit < cnt; + return cfg->gc_auto_pack_limit < cnt; } static uint64_t total_ram(void) @@ -336,7 +390,8 @@ static uint64_t total_ram(void) return 0; } -static uint64_t estimate_repack_memory(struct packed_git *pack) +static uint64_t estimate_repack_memory(struct gc_config *cfg, + struct packed_git *pack) { unsigned long nr_objects = repo_approximate_object_count(the_repository); size_t os_cache, heap; @@ -371,9 +426,9 @@ static uint64_t estimate_repack_memory(struct packed_git *pack) * read_sha1_file() (either at delta calculation phase, or * writing phase) also fills up the delta base cache */ - heap += delta_base_cache_limit; + heap += cfg->delta_base_cache_limit; /* and of course pack-objects has its own delta cache */ - heap += max_delta_cache_size; + heap += cfg->max_delta_cache_size; return os_cache + heap; } @@ -384,30 +439,31 @@ static int keep_one_pack(struct string_list_item *item, void *data UNUSED) return 0; } -static void add_repack_all_option(struct string_list *keep_pack) +static void add_repack_all_option(struct gc_config *cfg, + struct string_list *keep_pack) { - if (prune_expire && !strcmp(prune_expire, "now")) + if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")) strvec_push(&repack, "-a"); - else if (cruft_packs) { + else if (cfg->cruft_packs) { strvec_push(&repack, "--cruft"); - if (prune_expire) - strvec_pushf(&repack, "--cruft-expiration=%s", prune_expire); - if (max_cruft_size) + if (cfg->prune_expire) + strvec_pushf(&repack, "--cruft-expiration=%s", cfg->prune_expire); + if (cfg->max_cruft_size) strvec_pushf(&repack, "--max-cruft-size=%lu", - max_cruft_size); + cfg->max_cruft_size); } else { strvec_push(&repack, "-A"); - if (prune_expire) - strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire); + if (cfg->prune_expire) + strvec_pushf(&repack, "--unpack-unreachable=%s", cfg->prune_expire); } if (keep_pack) for_each_string_list(keep_pack, keep_one_pack, NULL); - if (repack_filter && *repack_filter) - strvec_pushf(&repack, "--filter=%s", repack_filter); - if (repack_filter_to && *repack_filter_to) - strvec_pushf(&repack, "--filter-to=%s", repack_filter_to); + if (cfg->repack_filter && *cfg->repack_filter) + strvec_pushf(&repack, "--filter=%s", cfg->repack_filter); + if (cfg->repack_filter_to && *cfg->repack_filter_to) + strvec_pushf(&repack, "--filter-to=%s", cfg->repack_filter_to); } static void add_repack_incremental_option(void) @@ -415,13 +471,13 @@ static void add_repack_incremental_option(void) strvec_push(&repack, "--no-write-bitmap-index"); } -static int need_to_gc(void) +static int need_to_gc(struct gc_config *cfg) { /* * Setting gc.auto to 0 or negative can disable the * automatic gc. */ - if (gc_auto_threshold <= 0) + if (cfg->gc_auto_threshold <= 0) return 0; /* @@ -430,13 +486,13 @@ static int need_to_gc(void) * we run "repack -A -d -l". Otherwise we tell the caller * there is no need. */ - if (too_many_packs()) { + if (too_many_packs(cfg)) { struct string_list keep_pack = STRING_LIST_INIT_NODUP; - if (big_pack_threshold) { - find_base_packs(&keep_pack, big_pack_threshold); - if (keep_pack.nr >= gc_auto_pack_limit) { - big_pack_threshold = 0; + if (cfg->big_pack_threshold) { + find_base_packs(&keep_pack, cfg->big_pack_threshold); + if (keep_pack.nr >= cfg->gc_auto_pack_limit) { + cfg->big_pack_threshold = 0; string_list_clear(&keep_pack, 0); find_base_packs(&keep_pack, 0); } @@ -445,7 +501,7 @@ static int need_to_gc(void) uint64_t mem_have, mem_want; mem_have = total_ram(); - mem_want = estimate_repack_memory(p); + mem_want = estimate_repack_memory(cfg, p); /* * Only allow 1/2 of memory for pack-objects, leave @@ -456,14 +512,14 @@ static int need_to_gc(void) string_list_clear(&keep_pack, 0); } - add_repack_all_option(&keep_pack); + add_repack_all_option(cfg, &keep_pack); string_list_clear(&keep_pack, 0); - } else if (too_many_loose_objects()) + } else if (too_many_loose_objects(cfg)) add_repack_incremental_option(); else return 0; - if (run_hooks("pre-auto-gc")) + if (run_hooks(the_repository, "pre-auto-gc")) return 0; return 1; } @@ -585,7 +641,8 @@ done: return ret; } -static void gc_before_repack(struct maintenance_run_opts *opts) +static void gc_before_repack(struct maintenance_run_opts *opts, + struct gc_config *cfg) { /* * We may be called twice, as both the pre- and @@ -596,10 +653,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts) if (done++) return; - if (pack_refs && maintenance_task_pack_refs(opts)) + if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg)) die(FAILED_RUN, "pack-refs"); - if (prune_reflogs) { + if (cfg->prune_reflogs) { struct child_process cmd = CHILD_PROCESS_INIT; cmd.git_cmd = 1; @@ -609,7 +666,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts) } } -int cmd_gc(int argc, const char **argv, const char *prefix) +int cmd_gc(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { int aggressive = 0; int quiet = 0; @@ -620,19 +680,25 @@ int cmd_gc(int argc, const char **argv, const char *prefix) int keep_largest_pack = -1; timestamp_t dummy; struct child_process rerere_cmd = CHILD_PROCESS_INIT; - struct maintenance_run_opts opts = {0}; + struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; + struct gc_config cfg = GC_CONFIG_INIT; + const char *prune_expire_sentinel = "sentinel"; + const char *prune_expire_arg = prune_expire_sentinel; + int ret; struct option builtin_gc_options[] = { OPT__QUIET(&quiet, N_("suppress progress reporting")), - { OPTION_STRING, 0, "prune", &prune_expire, N_("date"), + { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"), N_("prune unreferenced objects"), - PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire }, - OPT_BOOL(0, "cruft", &cruft_packs, N_("pack unreferenced objects separately")), - OPT_MAGNITUDE(0, "max-cruft-size", &max_cruft_size, + PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg }, + OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")), + OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size, N_("with --cruft, limit the size of new cruft packs")), OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")), OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"), PARSE_OPT_NOCOMPLETE), + OPT_BOOL(0, "detach", &opts.detach, + N_("perform garbage collection in the background")), OPT_BOOL_F(0, "force", &force, N_("force running gc even if there may be another gc running"), PARSE_OPT_NOCOMPLETE), @@ -650,84 +716,103 @@ int cmd_gc(int argc, const char **argv, const char *prefix) strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL); strvec_pushl(&rerere, "rerere", "gc", NULL); - /* default expiry time, overwritten in gc_config */ - gc_config(); - if (parse_expiry_date(gc_log_expire, &gc_log_expire_time)) - die(_("failed to parse gc.logExpiry value %s"), gc_log_expire); + gc_config(&cfg); - if (pack_refs < 0) - pack_refs = !is_bare_repository(); + if (parse_expiry_date(cfg.gc_log_expire, &gc_log_expire_time)) + die(_("failed to parse gc.logExpiry value %s"), cfg.gc_log_expire); + + if (cfg.pack_refs < 0) + cfg.pack_refs = !is_bare_repository(); argc = parse_options(argc, argv, prefix, builtin_gc_options, builtin_gc_usage, 0); if (argc > 0) usage_with_options(builtin_gc_usage, builtin_gc_options); - if (prune_expire && parse_expiry_date(prune_expire, &dummy)) - die(_("failed to parse prune expiry value %s"), prune_expire); + if (prune_expire_arg != prune_expire_sentinel) { + free(cfg.prune_expire); + cfg.prune_expire = xstrdup_or_null(prune_expire_arg); + } + if (cfg.prune_expire && parse_expiry_date(cfg.prune_expire, &dummy)) + die(_("failed to parse prune expiry value %s"), cfg.prune_expire); if (aggressive) { strvec_push(&repack, "-f"); - if (aggressive_depth > 0) - strvec_pushf(&repack, "--depth=%d", aggressive_depth); - if (aggressive_window > 0) - strvec_pushf(&repack, "--window=%d", aggressive_window); + if (cfg.aggressive_depth > 0) + strvec_pushf(&repack, "--depth=%d", cfg.aggressive_depth); + if (cfg.aggressive_window > 0) + strvec_pushf(&repack, "--window=%d", cfg.aggressive_window); } if (quiet) strvec_push(&repack, "-q"); if (opts.auto_flag) { + if (cfg.detach_auto && opts.detach < 0) + opts.detach = 1; + /* * Auto-gc should be least intrusive as possible. */ - if (!need_to_gc()) - return 0; + if (!need_to_gc(&cfg)) { + ret = 0; + goto out; + } + if (!quiet) { - if (detach_auto) + if (opts.detach > 0) fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n")); else fprintf(stderr, _("Auto packing the repository for optimum performance.\n")); fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n")); } - if (detach_auto) { - int ret = report_last_gc_error(); - - if (ret == 1) - /* Last gc --auto failed. Skip this one. */ - return 0; - else if (ret) - /* an I/O error occurred, already reported */ - return ret; - - if (lock_repo_for_gc(force, &pid)) - return 0; - gc_before_repack(&opts); /* dies on failure */ - delete_tempfile(&pidfile); - - /* - * failure to daemonize is ok, we'll continue - * in foreground - */ - daemonized = !daemonize(); - } } else { struct string_list keep_pack = STRING_LIST_INIT_NODUP; if (keep_largest_pack != -1) { if (keep_largest_pack) find_base_packs(&keep_pack, 0); - } else if (big_pack_threshold) { - find_base_packs(&keep_pack, big_pack_threshold); + } else if (cfg.big_pack_threshold) { + find_base_packs(&keep_pack, cfg.big_pack_threshold); } - add_repack_all_option(&keep_pack); + add_repack_all_option(&cfg, &keep_pack); string_list_clear(&keep_pack, 0); } + if (opts.detach > 0) { + ret = report_last_gc_error(); + if (ret == 1) { + /* Last gc --auto failed. Skip this one. */ + ret = 0; + goto out; + + } else if (ret) { + /* an I/O error occurred, already reported */ + goto out; + } + + if (lock_repo_for_gc(force, &pid)) { + ret = 0; + goto out; + } + + gc_before_repack(&opts, &cfg); /* dies on failure */ + delete_tempfile(&pidfile); + + /* + * failure to daemonize is ok, we'll continue + * in foreground + */ + daemonized = !daemonize(); + } + name = lock_repo_for_gc(force, &pid); if (name) { - if (opts.auto_flag) - return 0; /* be quiet on --auto */ + if (opts.auto_flag) { + ret = 0; + goto out; /* be quiet on --auto */ + } + die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"), name, (uintmax_t)pid); } @@ -737,11 +822,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) git_path("gc.log"), LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); - sigchain_push_common(process_log_file_on_signal); atexit(process_log_file_at_exit); } - gc_before_repack(&opts); + gc_before_repack(&opts, &cfg); if (!repository_format_precious_objects) { struct child_process repack_cmd = CHILD_PROCESS_INIT; @@ -752,11 +836,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (run_command(&repack_cmd)) die(FAILED_RUN, repack.v[0]); - if (prune_expire) { + if (cfg.prune_expire) { struct child_process prune_cmd = CHILD_PROCESS_INIT; /* run `git prune` even if using cruft packs */ - strvec_push(&prune, prune_expire); + strvec_push(&prune, cfg.prune_expire); if (quiet) strvec_push(&prune, "--no-progress"); if (repo_has_promisor_remote(the_repository)) @@ -769,10 +853,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) } } - if (prune_worktrees_expire) { + if (cfg.prune_worktrees_expire) { struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT; - strvec_push(&prune_worktrees, prune_worktrees_expire); + strvec_push(&prune_worktrees, cfg.prune_worktrees_expire); prune_worktrees_cmd.git_cmd = 1; strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v); if (run_command(&prune_worktrees_cmd)) @@ -796,13 +880,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix) !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0, NULL); - if (opts.auto_flag && too_many_loose_objects()) + if (opts.auto_flag && too_many_loose_objects(&cfg)) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); if (!daemonized) unlink(git_path("gc.log")); +out: + gc_config_release(&cfg); return 0; } @@ -836,6 +922,7 @@ struct cg_auto_data { }; static int dfs_on_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) @@ -892,7 +979,7 @@ static int dfs_on_ref(const char *refname UNUSED, return result; } -static int should_write_commit_graph(void) +static int should_write_commit_graph(struct gc_config *cfg UNUSED) { int result; struct cg_auto_data data; @@ -929,7 +1016,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts) return !!run_command(&child); } -static int maintenance_task_commit_graph(struct maintenance_run_opts *opts) +static int maintenance_task_commit_graph(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { prepare_repo_settings(the_repository); if (!the_repository->settings.core_commit_graph) @@ -963,7 +1051,8 @@ static int fetch_remote(struct remote *remote, void *cbdata) return !!run_command(&child); } -static int maintenance_task_prefetch(struct maintenance_run_opts *opts) +static int maintenance_task_prefetch(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { if (for_each_remote(fetch_remote, opts)) { error(_("failed to prefetch remotes")); @@ -973,7 +1062,8 @@ static int maintenance_task_prefetch(struct maintenance_run_opts *opts) return 0; } -static int maintenance_task_gc(struct maintenance_run_opts *opts) +static int maintenance_task_gc(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { struct child_process child = CHILD_PROCESS_INIT; @@ -986,6 +1076,7 @@ static int maintenance_task_gc(struct maintenance_run_opts *opts) strvec_push(&child.args, "--quiet"); else strvec_push(&child.args, "--no-quiet"); + strvec_push(&child.args, "--no-detach"); return run_command(&child); } @@ -1021,7 +1112,7 @@ static int loose_object_count(const struct object_id *oid UNUSED, return 0; } -static int loose_object_auto_condition(void) +static int loose_object_auto_condition(struct gc_config *cfg UNUSED) { int count = 0; @@ -1081,6 +1172,12 @@ static int pack_loose(struct maintenance_run_opts *opts) pack_proc.in = -1; + /* + * git-pack-objects(1) ends up writing the pack hash to stdout, which + * we do not care for. + */ + pack_proc.out = -1; + if (start_command(&pack_proc)) { error(_("failed to start 'git pack-objects' process")); return 1; @@ -1106,12 +1203,13 @@ static int pack_loose(struct maintenance_run_opts *opts) return result; } -static int maintenance_task_loose_objects(struct maintenance_run_opts *opts) +static int maintenance_task_loose_objects(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { return prune_packed(opts) || pack_loose(opts); } -static int incremental_repack_auto_condition(void) +static int incremental_repack_auto_condition(struct gc_config *cfg UNUSED) { struct packed_git *p; int incremental_repack_auto_limit = 10; @@ -1230,7 +1328,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts) return 0; } -static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts) +static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { prepare_repo_settings(the_repository); if (!the_repository->settings.core_multi_pack_index) { @@ -1247,14 +1346,15 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts return 0; } -typedef int maintenance_task_fn(struct maintenance_run_opts *opts); +typedef int maintenance_task_fn(struct maintenance_run_opts *opts, + struct gc_config *cfg); /* * An auto condition function returns 1 if the task should run * and 0 if the task should NOT run. See needs_to_gc() for an * example. */ -typedef int maintenance_auto_fn(void); +typedef int maintenance_auto_fn(struct gc_config *cfg); struct maintenance_task { const char *name; @@ -1321,7 +1421,8 @@ static int compare_tasks_by_selection(const void *a_, const void *b_) return b->selected_order - a->selected_order; } -static int maintenance_run_tasks(struct maintenance_run_opts *opts) +static int maintenance_run_tasks(struct maintenance_run_opts *opts, + struct gc_config *cfg) { int i, found_selected = 0; int result = 0; @@ -1345,6 +1446,13 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) } free(lock_path); + /* Failure to daemonize is ok, we'll continue in foreground. */ + if (opts->detach > 0) { + trace2_region_enter("maintenance", "detach", the_repository); + daemonize(); + trace2_region_leave("maintenance", "detach", the_repository); + } + for (i = 0; !found_selected && i < TASK__COUNT; i++) found_selected = tasks[i].selected_order >= 0; @@ -1360,14 +1468,14 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) if (opts->auto_flag && (!tasks[i].auto_condition || - !tasks[i].auto_condition())) + !tasks[i].auto_condition(cfg))) continue; if (opts->schedule && tasks[i].schedule < opts->schedule) continue; trace2_region_enter("maintenance", tasks[i].name, r); - if (tasks[i].fn(opts)) { + if (tasks[i].fn(opts, cfg)) { error(_("task '%s' failed"), tasks[i].name); result = 1; } @@ -1380,9 +1488,9 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) static void initialize_maintenance_strategy(void) { - char *config_str; + const char *config_str; - if (git_config_get_string("maintenance.strategy", &config_str)) + if (git_config_get_string_tmp("maintenance.strategy", &config_str)) return; if (!strcasecmp(config_str, "incremental")) { @@ -1404,7 +1512,6 @@ static void initialize_task_config(int schedule) { int i; struct strbuf config_name = STRBUF_INIT; - gc_config(); if (schedule) initialize_maintenance_strategy(); @@ -1464,13 +1571,17 @@ static int task_option_parse(const struct option *opt UNUSED, return 0; } -static int maintenance_run(int argc, const char **argv, const char *prefix) +static int maintenance_run(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i; - struct maintenance_run_opts opts; + struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; + struct gc_config cfg = GC_CONFIG_INIT; struct option builtin_maintenance_run_options[] = { OPT_BOOL(0, "auto", &opts.auto_flag, N_("run tasks based on the state of the repository")), + OPT_BOOL(0, "detach", &opts.detach, + N_("perform maintenance in the background")), OPT_CALLBACK(0, "schedule", &opts.schedule, N_("frequency"), N_("run tasks based on frequency"), maintenance_opt_schedule), @@ -1481,7 +1592,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix) PARSE_OPT_NONEG, task_option_parse), OPT_END() }; - memset(&opts, 0, sizeof(opts)); + int ret; opts.quiet = !isatty(2); @@ -1496,12 +1607,16 @@ static int maintenance_run(int argc, const char **argv, const char *prefix) if (opts.auto_flag && opts.schedule) die(_("use at most one of --auto and --schedule=<frequency>")); + gc_config(&cfg); initialize_task_config(opts.schedule); if (argc != 0) usage_with_options(builtin_maintenance_run_usage, builtin_maintenance_run_options); - return maintenance_run_tasks(&opts); + + ret = maintenance_run_tasks(&opts, &cfg); + gc_config_release(&cfg); + return ret; } static char *get_maintpath(void) @@ -1519,7 +1634,8 @@ static char const * const builtin_maintenance_register_usage[] = { NULL }; -static int maintenance_register(int argc, const char **argv, const char *prefix) +static int maintenance_register(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { char *config_file = NULL; struct option options[] = { @@ -1583,7 +1699,8 @@ static char const * const builtin_maintenance_unregister_usage[] = { NULL }; -static int maintenance_unregister(int argc, const char **argv, const char *prefix) +static int maintenance_unregister(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int force = 0; char *config_file = NULL; @@ -1664,6 +1781,42 @@ static const char *get_frequency(enum schedule_priority schedule) } } +static const char *extraconfig[] = { + "credential.interactive=false", + "core.askPass=true", /* 'true' returns success, but no output. */ + NULL +}; + +static const char *get_extra_config_parameters(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) + strbuf_addf(&builder, "-c %s ", *s); + + result = strbuf_detach(&builder, NULL); + return result; +} + +static const char *get_extra_launchctl_strings(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) { + strbuf_addstr(&builder, "<string>-c</string>\n"); + strbuf_addf(&builder, "<string>%s</string>\n", *s); + } + + result = strbuf_detach(&builder, NULL); + return result; +} + /* * get_schedule_cmd` reads the GIT_TEST_MAINT_SCHEDULER environment variable * to mock the schedulers that `git maintenance start` rely on. @@ -1678,39 +1831,43 @@ static const char *get_frequency(enum schedule_priority schedule) * * If $GIT_TEST_MAINT_SCHEDULER is set, return true. * In this case, the *cmd value is read as input. * - * * if the input value *cmd is the key of one of the comma-separated list - * item, then *is_available is set to true and *cmd is modified and becomes + * * if the input value cmd is the key of one of the comma-separated list + * item, then *is_available is set to true and *out is set to * the mock command. * * * if the input value *cmd isn’t the key of any of the comma-separated list - * item, then *is_available is set to false. + * item, then *is_available is set to false and *out is set to the original + * command. * * Ex.: * GIT_TEST_MAINT_SCHEDULER not set * +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ - * | "foo" | false | "foo" (unchanged) | (unchanged) | + * | "foo" | false | "foo" (allocated) | (unchanged) | * +-------+-------------+-------------------+---------------+ * * GIT_TEST_MAINT_SCHEDULER set to “foo:./mock_foo.sh,bar:./mock_bar.sh†* +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ * | "foo" | true | "./mock.foo.sh" | true | - * | "qux" | true | "qux" (unchanged) | false | + * | "qux" | true | "qux" (allocated) | false | * +-------+-------------+-------------------+---------------+ */ -static int get_schedule_cmd(const char **cmd, int *is_available) +static int get_schedule_cmd(const char *cmd, int *is_available, char **out) { char *testing = xstrdup_or_null(getenv("GIT_TEST_MAINT_SCHEDULER")); struct string_list_item *item; struct string_list list = STRING_LIST_INIT_NODUP; - if (!testing) + if (!testing) { + if (out) + *out = xstrdup(cmd); return 0; + } if (is_available) *is_available = 0; @@ -1722,16 +1879,22 @@ static int get_schedule_cmd(const char **cmd, int *is_available) if (string_list_split_in_place(&pair, item->string, ":", 2) != 2) continue; - if (!strcmp(*cmd, pair.items[0].string)) { - *cmd = pair.items[1].string; + if (!strcmp(cmd, pair.items[0].string)) { + if (out) + *out = xstrdup(pair.items[1].string); if (is_available) *is_available = 1; - string_list_clear(&list, 0); - UNLEAK(testing); - return 1; + string_list_clear(&pair, 0); + goto out; } + + string_list_clear(&pair, 0); } + if (out) + *out = xstrdup(cmd); + +out: string_list_clear(&list, 0); free(testing); return 1; @@ -1748,9 +1911,8 @@ static int get_random_minute(void) static int is_launchctl_available(void) { - const char *cmd = "launchctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("launchctl", &is_available, NULL)) return is_available; #ifdef __APPLE__ @@ -1788,12 +1950,12 @@ static char *launchctl_get_uid(void) static int launchctl_boot_plist(int enable, const char *filename) { - const char *cmd = "launchctl"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; char *uid = launchctl_get_uid(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, enable ? "bootstrap" : "bootout", uid, filename, NULL); @@ -1806,6 +1968,7 @@ static int launchctl_boot_plist(int enable, const char *filename) result = finish_command(&child); + free(cmd); free(uid); return result; } @@ -1857,10 +2020,10 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit static unsigned long lock_file_timeout_ms = ULONG_MAX; struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT; struct stat st; - const char *cmd = "launchctl"; + char *cmd; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); preamble = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">" @@ -1870,6 +2033,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "<array>\n" "<string>%s/git</string>\n" "<string>--exec-path=%s</string>\n" + "%s" /* For extra config parameters. */ "<string>for-each-repo</string>\n" "<string>--keep-going</string>\n" "<string>--config=maintenance.repo</string>\n" @@ -1879,7 +2043,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "</array>\n" "<key>StartCalendarInterval</key>\n" "<array>\n"; - strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency); + strbuf_addf(&plist, preamble, name, exec_path, exec_path, + get_extra_launchctl_strings(), frequency); switch (schedule) { case SCHEDULE_HOURLY: @@ -1950,6 +2115,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit free(filename); free(name); + free(cmd); strbuf_release(&plist); strbuf_release(&plist2); return 0; @@ -1974,9 +2140,8 @@ static int launchctl_update_schedule(int run_maintenance, int fd UNUSED) static int is_schtasks_available(void) { - const char *cmd = "schtasks"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("schtasks", &is_available, NULL)) return is_available; #ifdef GIT_WINDOWS_NATIVE @@ -1995,15 +2160,16 @@ static char *schtasks_task_name(const char *frequency) static int schtasks_remove_task(enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); char *name = schtasks_task_name(frequency); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/delete", "/tn", name, "/f", NULL); free(name); + free(cmd); return run_command(&child); } @@ -2017,7 +2183,7 @@ static int schtasks_remove_tasks(void) static int schtasks_schedule_task(const char *exec_path, enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; const char *xml; @@ -2027,10 +2193,10 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority struct strbuf tfilename = STRBUF_INIT; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strbuf_addf(&tfilename, "%s/schedule_%s_XXXXXX", - get_git_common_dir(), frequency); + repo_get_common_dir(the_repository), frequency); tfile = xmks_tempfile(tfilename.buf); strbuf_release(&tfilename); @@ -2114,11 +2280,12 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "<Actions Context=\"Author\">\n" "<Exec>\n" "<Command>\"%s\\headless-git.exe\"</Command>\n" - "<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" + "<Arguments>--exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" "</Exec>\n" "</Actions>\n" "</Task>\n"; - fprintf(tfile->fp, xml, exec_path, exec_path, frequency); + fprintf(tfile->fp, xml, exec_path, exec_path, + get_extra_config_parameters(), frequency); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml", get_tempfile_path(tfile), NULL); @@ -2133,6 +2300,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority delete_tempfile(&tfile); free(name); + free(cmd); return result; } @@ -2174,21 +2342,28 @@ static int check_crontab_process(const char *cmd) static int is_crontab_available(void) { - const char *cmd = "crontab"; + char *cmd; int is_available; + int ret; - if (get_schedule_cmd(&cmd, &is_available)) - return is_available; + if (get_schedule_cmd("crontab", &is_available, &cmd)) { + ret = is_available; + goto out; + } #ifdef __APPLE__ /* * macOS has cron, but it requires special permissions and will * create a UI alert when attempting to run this command. */ - return 0; + ret = 0; #else - return check_crontab_process(cmd); + ret = check_crontab_process(cmd); #endif + +out: + free(cmd); + return ret; } #define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE" @@ -2196,7 +2371,7 @@ static int is_crontab_available(void) static int crontab_update_schedule(int run_maintenance, int fd) { - const char *cmd = "crontab"; + char *cmd; int result = 0; int in_old_region = 0; struct child_process crontab_list = CHILD_PROCESS_INIT; @@ -2206,15 +2381,17 @@ static int crontab_update_schedule(int run_maintenance, int fd) struct tempfile *tmpedit = NULL; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("crontab", NULL, &cmd); strvec_split(&crontab_list.args, cmd); strvec_push(&crontab_list.args, "-l"); crontab_list.in = -1; crontab_list.out = dup(fd); crontab_list.git_cmd = 0; - if (start_command(&crontab_list)) - return error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + if (start_command(&crontab_list)) { + result = error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + goto out; + } /* Ignore exit code, as an empty crontab will return error. */ finish_command(&crontab_list); @@ -2259,8 +2436,8 @@ static int crontab_update_schedule(int run_maintenance, int fd) "# replaced in the future by a Git command.\n\n"); strbuf_addf(&line_format, - "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", - exec_path, exec_path); + "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", + exec_path, exec_path, get_extra_config_parameters()); fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly"); fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily"); fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly"); @@ -2284,8 +2461,10 @@ static int crontab_update_schedule(int run_maintenance, int fd) result = error(_("'crontab' died")); else fclose(cron_list); + out: delete_tempfile(&tmpedit); + free(cmd); return result; } @@ -2308,10 +2487,9 @@ static int real_is_systemd_timer_available(void) static int is_systemd_timer_available(void) { - const char *cmd = "systemctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("systemctl", &is_available, NULL)) return is_available; return real_is_systemd_timer_available(); @@ -2460,7 +2638,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "\n" "[Service]\n" "Type=oneshot\n" - "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" + "ExecStart=\"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" "LockPersonality=yes\n" "MemoryDenyWriteExecute=yes\n" "NoNewPrivileges=yes\n" @@ -2470,7 +2648,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "RestrictSUIDSGID=yes\n" "SystemCallArchitectures=native\n" "SystemCallFilter=@system-service\n"; - if (fprintf(file, unit, exec_path, exec_path) < 0) { + if (fprintf(file, unit, exec_path, exec_path, get_extra_config_parameters()) < 0) { error(_("failed to write to '%s'"), filename); fclose(file); goto error; @@ -2492,9 +2670,10 @@ static int systemd_timer_enable_unit(int enable, enum schedule_priority schedule, int minute) { - const char *cmd = "systemctl"; + char *cmd = NULL; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); + int ret; /* * Disabling the systemd unit while it is already disabled makes @@ -2505,20 +2684,25 @@ static int systemd_timer_enable_unit(int enable, * On the other hand, enabling a systemd unit which is already enabled * produces no error. */ - if (!enable) + if (!enable) { child.no_stderr = 1; - else if (systemd_timer_write_timer_file(schedule, minute)) - return -1; + } else if (systemd_timer_write_timer_file(schedule, minute)) { + ret = -1; + goto out; + } - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("systemctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "--user", enable ? "enable" : "disable", "--now", NULL); strvec_pushf(&child.args, SYSTEMD_UNIT_FORMAT, frequency, "timer"); - if (start_command(&child)) - return error(_("failed to start systemctl")); - if (finish_command(&child)) + if (start_command(&child)) { + ret = error(_("failed to start systemctl")); + goto out; + } + + if (finish_command(&child)) { /* * Disabling an already disabled systemd unit makes * systemctl fail. @@ -2526,9 +2710,17 @@ static int systemd_timer_enable_unit(int enable, * * Enabling an enabled systemd unit doesn't fail. */ - if (enable) - return error(_("failed to run systemctl")); - return 0; + if (enable) { + ret = error(_("failed to run systemctl")); + goto out; + } + } + + ret = 0; + +out: + free(cmd); + return ret; } /* @@ -2711,8 +2903,17 @@ static int update_background_schedule(const struct maintenance_start_opts *opts, char *lock_path = xstrfmt("%s/schedule", the_repository->objects->odb->path); if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) { + if (errno == EEXIST) + error(_("unable to create '%s.lock': %s.\n\n" + "Another scheduled git-maintenance(1) process seems to be running in this\n" + "repository. Please make sure no other maintenance processes are running and\n" + "then try again. If it still fails, a git-maintenance(1) process may have\n" + "crashed in this repository earlier: remove the file manually to continue."), + absolute_path(lock_path), strerror(errno)); + else + error_errno(_("cannot acquire lock for scheduled background maintenance")); free(lock_path); - return error(_("another process is scheduling background maintenance")); + return -1; } for (i = 1; i < ARRAY_SIZE(scheduler_fn); i++) { @@ -2738,7 +2939,8 @@ static const char *const builtin_maintenance_start_usage[] = { NULL }; -static int maintenance_start(int argc, const char **argv, const char *prefix) +static int maintenance_start(int argc, const char **argv, const char *prefix, + struct repository *repo) { struct maintenance_start_opts opts = { 0 }; struct option options[] = { @@ -2761,7 +2963,7 @@ static int maintenance_start(int argc, const char **argv, const char *prefix) if (update_background_schedule(&opts, 1)) die(_("failed to set up maintenance schedule")); - if (maintenance_register(ARRAY_SIZE(register_args)-1, register_args, NULL)) + if (maintenance_register(ARRAY_SIZE(register_args)-1, register_args, NULL, repo)) warning(_("failed to add repo to global config")); return 0; } @@ -2771,7 +2973,8 @@ static const char *const builtin_maintenance_stop_usage[] = { NULL }; -static int maintenance_stop(int argc, const char **argv, const char *prefix) +static int maintenance_stop(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -2788,7 +2991,10 @@ static const char * const builtin_maintenance_usage[] = { NULL, }; -int cmd_maintenance(int argc, const char **argv, const char *prefix) +int cmd_maintenance(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_maintenance_options[] = { @@ -2802,5 +3008,5 @@ int cmd_maintenance(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_maintenance_options, builtin_maintenance_usage, 0); - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index 66a7389f9f..6bec0d1854 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -12,7 +12,10 @@ static const char builtin_get_tar_commit_id_usage[] = #define RECORDSIZE (512) #define HEADERSIZE (2 * RECORDSIZE) -int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix) +int cmd_get_tar_commit_id(int argc, + const char **argv UNUSED, + const char *prefix, + struct repository *repo UNUSED) { char buffer[HEADERSIZE]; struct ustar_header *header = (struct ustar_header *)buffer; @@ -35,6 +38,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix if (header->typeflag[0] != TYPEFLAG_GLOBAL_HEADER) return 1; + errno = 0; len = strtol(content, &end, 10); if (errno == ERANGE || end == content || len < 0) return 1; diff --git a/builtin/grep.c b/builtin/grep.c index dfc3c3e8bd..98b85c7fca 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -3,11 +3,11 @@ * * Copyright (c) 2006 Junio C Hamano */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "tag.h" #include "tree-walk.h" @@ -888,7 +888,10 @@ static int pattern_callback(const struct option *opt, const char *arg, return 0; } -int cmd_grep(int argc, const char **argv, const char *prefix) +int cmd_grep(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int hit = 0; int cached = 0, untracked = 0, opt_exclude = -1; @@ -903,6 +906,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) int dummy; int use_index = 1; int allow_revs; + int ret; struct option options[] = { OPT_BOOL(0, "cached", &cached, @@ -1133,6 +1137,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) &oid, &oc)) { if (seen_dashdash) die(_("unable to resolve revision: %s"), arg); + object_context_release(&oc); break; } @@ -1168,8 +1173,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix) * Optimize out the case where the amount of matches is limited to zero. * We do this to keep results consistent with GNU grep(1). */ - if (opt.max_count == 0) - return 1; + if (opt.max_count == 0) { + ret = 1; + goto out; + } if (show_in_pager) { if (num_threads > 1) @@ -1263,10 +1270,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix) hit |= wait_all(); if (hit && show_in_pager) run_pager(&opt, prefix); + + ret = !hit; + +out: clear_pathspec(&pathspec); string_list_clear(&path_list, 0); free_grep_patterns(&opt); object_array_clear(&list); free_repos(); - return !hit; + return ret; } diff --git a/builtin/hash-object.c b/builtin/hash-object.c index c767414a0c..a25f0403f4 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -4,6 +4,7 @@ * Copyright (C) Linus Torvalds, 2005 * Copyright (C) Junio C Hamano, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -84,7 +85,10 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, strbuf_release(&unquoted); } -int cmd_hash_object(int argc, const char **argv, const char *prefix) +int cmd_hash_object(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static const char * const hash_object_usage[] = { N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" diff --git a/builtin/help.c b/builtin/help.c index dc1fbe2b98..6a72d991a8 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -1,6 +1,8 @@ + /* * Builtin help command */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "exec-cmd.h" @@ -52,7 +54,7 @@ static enum help_action { HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION, } cmd_mode; -static const char *html_path; +static char *html_path; static int verbose = 1; static enum help_format help_format = HELP_FORMAT_NONE; static int exclude_guides; @@ -409,6 +411,7 @@ static int git_help_config(const char *var, const char *value, if (!strcmp(var, "help.htmlpath")) { if (!value) return config_error_nonbool(var); + free(html_path); html_path = xstrdup(value); return 0; } @@ -513,23 +516,24 @@ static void show_info_page(const char *page) static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; + const char *path = html_path; char *to_free = NULL; - if (!html_path) - html_path = to_free = system_path(GIT_HTML_PATH); + if (!path) + path = to_free = system_path(GIT_HTML_PATH); /* * Check that the page we're looking for exists. */ - if (!strstr(html_path, "://")) { - if (stat(mkpath("%s/%s.html", html_path, page), &st) + if (!strstr(path, "://")) { + if (stat(mkpath("%s/%s.html", path, page), &st) || !S_ISREG(st.st_mode)) die("'%s/%s.html': documentation file not found.", - html_path, page); + path, page); } strbuf_init(page_path, 0); - strbuf_addf(page_path, "%s/%s.html", html_path, page); + strbuf_addf(page_path, "%s/%s.html", path, page); free(to_free); } @@ -540,19 +544,19 @@ static void open_html(const char *path) static void show_html_page(const char *page) { - struct strbuf page_path; /* it leaks but we exec bellow */ + struct strbuf page_path; /* it leaks but we exec below */ get_html_page_path(&page_path, page); open_html(page_path.buf); } -static const char *check_git_cmd(const char* cmd) +static char *check_git_cmd(const char *cmd) { char *alias; if (is_git_command(cmd)) - return cmd; + return xstrdup(cmd); alias = alias_lookup(cmd); if (alias) { @@ -585,14 +589,13 @@ static const char *check_git_cmd(const char* cmd) die(_("bad alias.%s string: %s"), cmd, split_cmdline_strerror(count)); free(argv); - UNLEAK(alias); return alias; } if (exclude_guides) return help_unknown_cmd(cmd); - return cmd; + return xstrdup(cmd); } static void no_help_format(const char *opt_mode, enum help_format fmt) @@ -631,10 +634,14 @@ static void opt_mode_usage(int argc, const char *opt_mode, no_help_format(opt_mode, fmt); } -int cmd_help(int argc, const char **argv, const char *prefix) +int cmd_help(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int nongit; enum help_format parsed_help_format; + char *command = NULL; const char *page; argc = parse_options(argc, argv, prefix, builtin_help_options, @@ -706,9 +713,9 @@ int cmd_help(int argc, const char **argv, const char *prefix) if (help_format == HELP_FORMAT_NONE) help_format = parse_help_format(DEFAULT_HELP_FORMAT); - argv[0] = check_git_cmd(argv[0]); + command = check_git_cmd(argv[0]); - page = cmd_to_page(argv[0]); + page = cmd_to_page(command); switch (help_format) { case HELP_FORMAT_NONE: case HELP_FORMAT_MAN: @@ -722,5 +729,6 @@ int cmd_help(int argc, const char **argv, const char *prefix) break; } + free(command); return 0; } diff --git a/builtin/hook.c b/builtin/hook.c index 5234693a94..672d2e37e8 100644 --- a/builtin/hook.c +++ b/builtin/hook.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -18,7 +19,8 @@ static const char * const builtin_hook_run_usage[] = { NULL }; -static int run(int argc, const char **argv, const char *prefix) +static int run(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i; struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; @@ -58,7 +60,7 @@ static int run(int argc, const char **argv, const char *prefix) hook_name = argv[0]; if (!ignore_missing) opt.error_if_missing = 1; - ret = run_hooks_opt(hook_name, &opt); + ret = run_hooks_opt(the_repository, hook_name, &opt); if (ret < 0) /* error() return */ ret = 1; return ret; @@ -66,7 +68,10 @@ usage: usage_with_options(builtin_hook_run_usage, run_options); } -int cmd_hook(int argc, const char **argv, const char *prefix) +int cmd_hook(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_hook_options[] = { @@ -77,5 +82,5 @@ int cmd_hook(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, NULL, builtin_hook_options, builtin_hook_usage, 0); - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/index-pack.c b/builtin/index-pack.c index fd968d673d..acd744542b 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "delta.h" @@ -8,6 +9,7 @@ #include "csum-file.h" #include "blob.h" #include "commit.h" +#include "tag.h" #include "tree.h" #include "progress.h" #include "fsck.h" @@ -19,9 +21,14 @@ #include "object-file.h" #include "object-store-ll.h" #include "oid-array.h" +#include "oidset.h" +#include "path.h" #include "replace-object.h" +#include "tree-walk.h" #include "promisor-remote.h" +#include "run-command.h" #include "setup.h" +#include "strvec.h" static const char index_pack_usage[] = "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict[=<msg-id>=<severity>...]] [--fsck-objects[=<msg-id>=<severity>...]] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; @@ -93,7 +100,7 @@ static LIST_HEAD(done_head); static size_t base_cache_used; static size_t base_cache_limit; -struct thread_local { +struct thread_local_data { pthread_t thread; int pack_fd; }; @@ -116,7 +123,7 @@ static struct object_entry *objects; static struct object_stat *obj_stat; static struct ofs_delta_entry *ofs_deltas; static struct ref_delta_entry *ref_deltas; -static struct thread_local nothread_data; +static struct thread_local_data nothread_data; static int nr_objects; static int nr_ofs_deltas; static int nr_ref_deltas; @@ -147,7 +154,14 @@ static uint32_t input_crc32; static int input_fd, output_fd; static const char *curr_pack; -static struct thread_local *thread_data; +/* + * local_links is guarded by read_mutex, and record_local_links is read-only in + * a thread. + */ +static struct oidset local_links = OIDSET_INIT; +static int record_local_links; + +static struct thread_local_data *thread_data; static int nr_dispatched; static int threads_active; @@ -389,7 +403,7 @@ static NORETURN void bad_object(off_t offset, const char *format, ...) (uintmax_t)offset, buf); } -static inline struct thread_local *get_thread_data(void) +static inline struct thread_local_data *get_thread_data(void) { if (HAVE_THREADS) { if (threads_active) @@ -400,7 +414,7 @@ static inline struct thread_local *get_thread_data(void) return ¬hread_data; } -static void set_thread_data(struct thread_local *data) +static void set_thread_data(struct thread_local_data *data) { if (threads_active) pthread_setspecific(key, data); @@ -798,6 +812,44 @@ static int check_collison(struct object_entry *entry) return 0; } +static void record_if_local_object(const struct object_id *oid) +{ + struct object_info info = OBJECT_INFO_INIT; + if (oid_object_info_extended(the_repository, oid, &info, 0)) + /* Missing; assume it is a promisor object */ + return; + if (info.whence == OI_PACKED && info.u.packed.pack->pack_promisor) + return; + oidset_insert(&local_links, oid); +} + +static void do_record_local_links(struct object *obj) +{ + if (obj->type == OBJ_TREE) { + struct tree *tree = (struct tree *)obj; + struct tree_desc desc; + struct name_entry entry; + if (init_tree_desc_gently(&desc, &tree->object.oid, + tree->buffer, tree->size, 0)) + /* + * Error messages are given when packs are + * verified, so do not print any here. + */ + return; + while (tree_entry_gently(&desc, &entry)) + record_if_local_object(&entry.oid); + } else if (obj->type == OBJ_COMMIT) { + struct commit *commit = (struct commit *) obj; + struct commit_list *parents = commit->parents; + + for (; parents; parents = parents->next) + record_if_local_object(&parents->item->object.oid); + } else if (obj->type == OBJ_TAG) { + struct tag *tag = (struct tag *) obj; + record_if_local_object(get_tagged_oid(tag)); + } +} + static void sha1_object(const void *data, struct object_entry *obj_entry, unsigned long size, enum object_type type, const struct object_id *oid) @@ -844,7 +896,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, free(has_data); } - if (strict || do_fsck_object) { + if (strict || do_fsck_object || record_local_links) { read_lock(); if (type == OBJ_BLOB) { struct blob *blob = lookup_blob(the_repository, oid); @@ -876,6 +928,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, die(_("fsck error in packed object")); if (strict && fsck_walk(obj, NULL, &fsck_options)) die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid)); + if (record_local_links) + do_record_local_links(obj); if (obj->type == OBJ_TREE) { struct tree *item = (struct tree *) obj; @@ -1237,7 +1291,7 @@ static void parse_pack_objects(unsigned char *hash) * recursively checking if the resulting object is used as a base * for some more deltas. */ -static void resolve_deltas(void) +static void resolve_deltas(struct pack_idx_option *opts) { int i; @@ -1253,7 +1307,7 @@ static void resolve_deltas(void) nr_ref_deltas + nr_ofs_deltas); nr_dispatched = 0; - base_cache_limit = delta_base_cache_limit * nr_threads; + base_cache_limit = opts->delta_base_cache_limit * nr_threads; if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) { init_thread(); work_lock(); @@ -1478,7 +1532,7 @@ static void write_special_file(const char *suffix, const char *msg, if (pack_name) filename = derive_filename(pack_name, "pack", suffix, &name_buf); else - filename = odb_pack_name(&name_buf, hash, suffix); + filename = odb_pack_name(the_repository, &name_buf, hash, suffix); fd = odb_pack_keep(filename); if (fd < 0) { @@ -1504,9 +1558,9 @@ static void rename_tmp_packfile(const char **final_name, struct strbuf *name, unsigned char *hash, const char *ext, int make_read_only_if_same) { - if (*final_name != curr_name) { + if (!*final_name || strcmp(*final_name, curr_name)) { if (!*final_name) - *final_name = odb_pack_name(name, hash, ext); + *final_name = odb_pack_name(the_repository, name, hash, ext); if (finalize_object_file(curr_name, *final_name)) die(_("unable to rename temporary '*.%s' file to '%s'"), ext, *final_name); @@ -1551,7 +1605,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name, if (do_fsck_object) { struct packed_git *p; - p = add_packed_git(final_index_name, strlen(final_index_name), 0); + p = add_packed_git(the_repository, final_index_name, + strlen(final_index_name), 0); if (p) install_packed_git(the_repository, p); } @@ -1602,6 +1657,10 @@ static int git_index_pack_config(const char *k, const char *v, else opts->flags &= ~WRITE_REV; } + if (!strcmp(k, "core.deltabasecachelimit")) { + opts->delta_base_cache_limit = git_config_ulong(k, v, ctx->kvi); + return 0; + } return git_default_config(k, v, ctx, cb); } @@ -1649,7 +1708,8 @@ static void read_v2_anomalous_offsets(struct packed_git *p, static void read_idx_option(struct pack_idx_option *opts, const char *pack_name) { - struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1); + struct packed_git *p = add_packed_git(the_repository, pack_name, + strlen(pack_name), 1); if (!p) die(_("Cannot open existing pack file '%s'"), pack_name); @@ -1718,11 +1778,66 @@ static void show_pack_info(int stat_only) free(chain_histogram); } -int cmd_index_pack(int argc, const char **argv, const char *prefix) +static void repack_local_links(void) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + FILE *out; + struct strbuf line = STRBUF_INIT; + struct oidset_iter iter; + struct object_id *oid; + char *base_name; + + if (!oidset_size(&local_links)) + return; + + base_name = mkpathdup("%s/pack/pack", repo_get_object_directory(the_repository)); + + strvec_push(&cmd.args, "pack-objects"); + strvec_push(&cmd.args, "--exclude-promisor-objects-best-effort"); + strvec_push(&cmd.args, base_name); + cmd.git_cmd = 1; + cmd.in = -1; + cmd.out = -1; + if (start_command(&cmd)) + die(_("could not start pack-objects to repack local links")); + + oidset_iter_init(&local_links, &iter); + while ((oid = oidset_iter_next(&iter))) { + if (write_in_full(cmd.in, oid_to_hex(oid), the_hash_algo->hexsz) < 0 || + write_in_full(cmd.in, "\n", 1) < 0) + die(_("failed to feed local object to pack-objects")); + } + close(cmd.in); + + out = xfdopen(cmd.out, "r"); + while (strbuf_getline_lf(&line, out) != EOF) { + unsigned char binary[GIT_MAX_RAWSZ]; + if (line.len != the_hash_algo->hexsz || + !hex_to_bytes(binary, line.buf, line.len)) + die(_("index-pack: Expecting full hex object ID lines only from pack-objects.")); + + /* + * pack-objects creates the .pack and .idx files, but not the + * .promisor file. Create the .promisor file, which is empty. + */ + write_special_file("promisor", "", NULL, binary, NULL); + } + + fclose(out); + if (finish_command(&cmd)) + die(_("could not finish pack-objects to repack local links")); + strbuf_release(&line); + free(base_name); +} + +int cmd_index_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; const char *curr_index; - const char *curr_rev_index = NULL; + char *curr_rev_index = NULL; const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; const char *keep_msg = NULL; const char *promisor_msg = NULL; @@ -1790,7 +1905,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) } else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) { ; /* nothing to do */ } else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) { - ; /* already parsed */ + record_local_links = 1; } else if (starts_with(arg, "--threads=")) { char *end; nr_threads = strtoul(arg+10, &end, 0); @@ -1861,6 +1976,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) usage(index_pack_usage); if (fix_thin_pack && !from_stdin) die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin"); + if (promisor_msg && pack_name) + die(_("--promisor cannot be used with a pack name")); if (from_stdin && !startup_info->have_repository) die(_("--stdin requires a git repository")); if (from_stdin && hash_algo) @@ -1868,6 +1985,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (!index_name && pack_name) index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf); + /* + * Packfiles and indices do not carry enough information to be able to + * identify their object hash. So when we are neither in a repository + * nor has the user told us which object hash to use we have no other + * choice but to guess the object hash. + */ + if (!the_repository->hash_algo) + repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY); if (rev_index) { opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV; @@ -1915,7 +2041,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) parse_pack_objects(pack_hash); if (report_end_of_input) write_in_full(2, "\0", 1); - resolve_deltas(); + resolve_deltas(&opts); conclude_pack(fix_thin_pack, curr_pack, pack_hash); free(ofs_deltas); free(ref_deltas); @@ -1955,8 +2081,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) free((void *) curr_pack); if (!index_name) free((void *) curr_index); - if (!rev_index_name) - free((void *) curr_rev_index); + free(curr_rev_index); + + repack_local_links(); /* * Let the caller know this pack is not self contained diff --git a/builtin/init-db.c b/builtin/init-db.c index 582dcf20f8..096f96b9c4 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -3,6 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" @@ -11,7 +12,6 @@ #include "parse-options.h" #include "path.h" #include "refs.h" -#include "repository.h" #include "setup.h" #include "strbuf.h" @@ -70,12 +70,17 @@ static const char *const init_db_usage[] = { * On the other hand, it might just make lookup slower and messier. You * be the judge. The default case is to have one DB per managed directory. */ -int cmd_init_db(int argc, const char **argv, const char *prefix) +int cmd_init_db(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { - const char *git_dir; + char *git_dir; const char *real_git_dir = NULL; - const char *work_tree; + char *real_git_dir_to_free = NULL; + char *work_tree = NULL; const char *template_dir = NULL; + char *template_dir_to_free = NULL; unsigned int flags = 0; const char *object_format = NULL; const char *ref_format = NULL; @@ -103,6 +108,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) N_("specify the reference format to use")), OPT_END() }; + int ret; argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0); @@ -110,12 +116,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare"); if (real_git_dir && !is_absolute_path(real_git_dir)) - real_git_dir = real_pathdup(real_git_dir, 1); + real_git_dir = real_git_dir_to_free = real_pathdup(real_git_dir, 1); - if (template_dir && *template_dir && !is_absolute_path(template_dir)) { - template_dir = absolute_pathdup(template_dir); - UNLEAK(template_dir); - } + if (template_dir && *template_dir && !is_absolute_path(template_dir)) + template_dir = template_dir_to_free = absolute_pathdup(template_dir); if (argc == 1) { int mkdir_tried = 0; @@ -189,7 +193,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) * Set up the default .git directory contents */ if (!git_dir) - git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; + git_dir = xstrdup(DEFAULT_GIT_DIR_ENVIRONMENT); /* * When --separate-git-dir is used inside a linked worktree, take @@ -210,6 +214,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) if (chdir(mainwt.buf) < 0) die_errno(_("cannot chdir to %s"), mainwt.buf); strbuf_release(&mainwt); + free(git_dir); git_dir = strbuf_detach(&sb, NULL); } strbuf_release(&sb); @@ -231,9 +236,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) set_git_work_tree(work_tree); else set_git_work_tree(git_work_tree_cfg); - if (access(get_git_work_tree(), X_OK)) + if (access(repo_get_work_tree(the_repository), X_OK)) die_errno (_("Cannot access work tree '%s'"), - get_git_work_tree()); + repo_get_work_tree(the_repository)); } else { if (real_git_dir) @@ -242,12 +247,14 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) set_git_work_tree(work_tree); } - UNLEAK(real_git_dir); - UNLEAK(git_dir); - UNLEAK(work_tree); - flags |= INIT_DB_EXIST_OK; - return init_db(git_dir, real_git_dir, template_dir, hash_algo, - ref_storage_format, initial_branch, - init_shared_repository, flags); + ret = init_db(git_dir, real_git_dir, template_dir, hash_algo, + ref_storage_format, initial_branch, + init_shared_repository, flags); + + free(template_dir_to_free); + free(real_git_dir_to_free); + free(work_tree); + free(git_dir); + return ret; } diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 1d969494cf..44d8ccddc9 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -4,7 +4,7 @@ * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org> * */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "parse-options.h" @@ -132,6 +132,7 @@ static void read_input_file(struct strbuf *sb, const char *file) if (strbuf_read(sb, fileno(stdin), 0) < 0) die_errno(_("could not read from stdin")); } + strbuf_complete_line(sb); } static void interpret_trailers(const struct process_trailer_options *opts, @@ -140,8 +141,8 @@ static void interpret_trailers(const struct process_trailer_options *opts, { LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; - struct strbuf trailer_block = STRBUF_INIT; - struct trailer_info *info; + struct strbuf trailer_block_sb = STRBUF_INIT; + struct trailer_block *trailer_block; FILE *outfile = stdout; trailer_config_init(); @@ -151,13 +152,13 @@ static void interpret_trailers(const struct process_trailer_options *opts, if (opts->in_place) outfile = create_in_place_tempfile(file); - info = parse_trailers(opts, sb.buf, &head); + trailer_block = parse_trailers(opts, sb.buf, &head); - /* Print the lines before the trailers */ + /* Print the lines before the trailer block */ if (!opts->only_trailers) - fwrite(sb.buf, 1, trailer_block_start(info), outfile); + fwrite(sb.buf, 1, trailer_block_start(trailer_block), outfile); - if (!opts->only_trailers && !blank_line_before_trailer_block(info)) + if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block)) fprintf(outfile, "\n"); @@ -171,15 +172,16 @@ static void interpret_trailers(const struct process_trailer_options *opts, } /* Print trailer block. */ - format_trailers(opts, &head, &trailer_block); + format_trailers(opts, &head, &trailer_block_sb); free_trailers(&head); - fwrite(trailer_block.buf, 1, trailer_block.len, outfile); - strbuf_release(&trailer_block); + fwrite(trailer_block_sb.buf, 1, trailer_block_sb.len, outfile); + strbuf_release(&trailer_block_sb); - /* Print the lines after the trailers as is */ + /* Print the lines after the trailer block as is. */ if (!opts->only_trailers) - fwrite(sb.buf + trailer_block_end(info), 1, sb.len - trailer_block_end(info), outfile); - trailer_info_release(info); + fwrite(sb.buf + trailer_block_end(trailer_block), 1, + sb.len - trailer_block_end(trailer_block), outfile); + trailer_block_release(trailer_block); if (opts->in_place) if (rename_tempfile(&trailers_tempfile, file)) @@ -188,7 +190,10 @@ static void interpret_trailers(const struct process_trailer_options *opts, strbuf_release(&sb); } -int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) +int cmd_interpret_trailers(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; LIST_HEAD(trailers); diff --git a/builtin/log.c b/builtin/log.c index a73a767606..368f6580a6 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -4,6 +4,7 @@ * (C) Copyright 2006 Linus Torvalds * 2006 Junio Hamano */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -37,7 +38,7 @@ #include "mailmap.h" #include "progress.h" #include "commit-slab.h" -#include "repository.h" + #include "commit-reach.h" #include "range-diff.h" #include "tmp-objdir.h" @@ -504,13 +505,7 @@ static int cmd_log_walk_no_free(struct rev_info *rev) struct commit *commit; int saved_nrl = 0; int saved_dcctc = 0; - - if (rev->remerge_diff) { - rev->remerge_objdir = tmp_objdir_create("remerge-diff"); - if (!rev->remerge_objdir) - die(_("unable to create temporary object directory")); - tmp_objdir_replace_primary_odb(rev->remerge_objdir, 1); - } + int result; if (rev->early_output) setup_early_output(); @@ -551,16 +546,12 @@ static int cmd_log_walk_no_free(struct rev_info *rev) rev->diffopt.degraded_cc_to_c = saved_dcctc; rev->diffopt.needed_rename_limit = saved_nrl; - if (rev->remerge_diff) { - tmp_objdir_destroy(rev->remerge_objdir); - rev->remerge_objdir = NULL; - } - + result = diff_result_code(rev); if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && rev->diffopt.flags.check_failed) { - return 02; + result = 02; } - return diff_result_code(&rev->diffopt); + return result; } static int cmd_log_walk(struct rev_info *rev) @@ -637,7 +628,10 @@ static int git_log_config(const char *var, const char *value, return git_diff_ui_config(var, value, ctx, cb); } -int cmd_whatchanged(int argc, const char **argv, const char *prefix) +int cmd_whatchanged(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -707,6 +701,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c write_or_die(1, buf, size); object_context_release(&obj_context); + free(buf); return 0; } @@ -757,7 +752,10 @@ static void show_setup_revisions_tweak(struct rev_info *rev) rev->diffopt.output_format = DIFF_FORMAT_PATCH; } -int cmd_show(int argc, const char **argv, const char *prefix) +int cmd_show(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -873,7 +871,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) /* * This is equivalent to "git log -g --abbrev-commit --pretty=oneline" */ -int cmd_log_reflog(int argc, const char **argv, const char *prefix) +int cmd_log_reflog(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -915,7 +916,10 @@ static void log_setup_revisions_tweak(struct rev_info *rev) diff_merges_default_to_first_parent(rev); } -int cmd_log(int argc, const char **argv, const char *prefix) +int cmd_log(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -1827,12 +1831,14 @@ static struct commit *get_base_commit(const struct format_config *cfg, if (die_on_failure) { die(_("failed to find exact merge base")); } else { + free_commit_list(merge_base); free(rev); return NULL; } } rev[i] = merge_base->item; + free_commit_list(merge_base); } if (rev_nr % 2) @@ -1983,7 +1989,10 @@ static void infer_range_diff_ranges(struct strbuf *r1, } } -int cmd_format_patch(int argc, const char **argv, const char *prefix) +int cmd_format_patch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct format_config cfg; struct commit *commit; @@ -2023,6 +2032,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *rfc = NULL; int creation_factor = -1; const char *signature = git_version_string; + char *signature_to_free = NULL; char *signature_file_arg = NULL; struct keep_callback_data keep_callback_data = { .cfg = &cfg, @@ -2443,7 +2453,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (strbuf_read_file(&buf, signature_file, 128) < 0) die_errno(_("unable to read signature file '%s'"), signature_file); - signature = strbuf_detach(&buf, NULL); + signature = signature_to_free = strbuf_detach(&buf, NULL); } else if (cfg.signature) { signature = cfg.signature; } @@ -2548,12 +2558,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) else print_signature(signature, rev.diffopt.file); } - if (output_directory) + if (output_directory) { fclose(rev.diffopt.file); + rev.diffopt.file = NULL; + } } stop_progress(&progress); free(list); - free(branch_name); if (ignore_if_in_upstream) free_patch_ids(&ids); @@ -2565,11 +2576,14 @@ done: strbuf_release(&rdiff_title); free(description_file); free(signature_file_arg); + free(signature_to_free); + free(branch_name); free(to_free); free(rev.message_id); if (rev.ref_message_ids) string_list_clear(rev.ref_message_ids, 0); free(rev.ref_message_ids); + rev.diffopt.no_free = 0; release_revisions(&rev); format_config_release(&cfg); return 0; @@ -2611,7 +2625,10 @@ static void print_commit(char sign, struct commit *commit, int verbose, } } -int cmd_cherry(int argc, const char **argv, const char *prefix) +int cmd_cherry(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct patch_ids ids; diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 6eeb5cba78..e016b0415d 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -5,8 +5,8 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" -#include "repository.h" #include "config.h" #include "convert.h" #include "quote.h" @@ -507,7 +507,7 @@ static int get_common_prefix_len(const char *common_prefix) common_prefix_len = strlen(common_prefix); /* - * If the prefix has a trailing slash, strip it so that submodules wont + * If the prefix has a trailing slash, strip it so that submodules won't * be pruned from the index. */ if (common_prefix[common_prefix_len - 1] == '/') @@ -561,7 +561,10 @@ static int option_parse_exclude_standard(const struct option *opt, return 0; } -int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) +int cmd_ls_files(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 5b61af5d78..42f34e1236 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -37,7 +38,10 @@ static int tail_match(const struct strvec *pattern, const char *path) return 0; } -int cmd_ls_remote(int argc, const char **argv, const char *prefix) +int cmd_ls_remote(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *dest = NULL; unsigned flags = 0; @@ -90,6 +94,21 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) PARSE_OPT_STOP_AT_NON_OPTION); dest = argv[0]; + /* + * TODO: This is buggy, but required for transport helpers. When a + * transport helper advertises a "refspec", then we'd add that to a + * list of refspecs via `refspec_append()`, which transitively depends + * on `the_hash_algo`. Thus, when the hash algorithm isn't properly set + * up, this would lead to a segfault. + * + * We really should fix this in the transport helper logic such that we + * lazily parse refspec capabilities _after_ we have learned about the + * remote's object format. Otherwise, we may end up misparsing refspecs + * depending on what object hash the remote uses. + */ + if (!the_repository->hash_algo) + repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + packet_trace_identity("ls-remote"); for (int i = 1; i < argc; i++) @@ -147,6 +166,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) status = 0; /* we found something */ } + string_list_clear(&server_options, 0); ref_sorting_release(sorting); ref_array_clear(&ref_array); if (transport_disconnect(transport)) @@ -154,5 +174,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) transport_ls_refs_options_release(&transport_options); strvec_clear(&pattern); + string_list_clear(&server_options, 0); return status; } diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index bf372c67d7..8542b5d53e 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -3,7 +3,9 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "config.h" #include "gettext.h" #include "hex.h" @@ -329,7 +331,10 @@ static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = { }, }; -int cmd_ls_tree(int argc, const char **argv, const char *prefix) +int cmd_ls_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct object_id oid; struct tree *tree; diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 53a22645da..e17dec27b1 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -2,6 +2,7 @@ * Another stupid program, this one parsing the headers of an * email to figure out authorship and subject */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" @@ -48,7 +49,10 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un return 0; } -int cmd_mailinfo(int argc, const char **argv, const char *prefix) +int cmd_mailinfo(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct metainfo_charset meta_charset; struct mailinfo mi; diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index fe6dbc5d05..b8f7150ce9 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -269,7 +269,10 @@ out: return ret; } -int cmd_mailsplit(int argc, const char **argv, const char *prefix) +int cmd_mailsplit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int nr = 0, nr_prec = 4, num = 0; int allow_bare = 0; diff --git a/builtin/merge-base.c b/builtin/merge-base.c index 5a8e729502..a20c93b11a 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -5,7 +6,6 @@ #include "hex.h" #include "object-name.h" #include "parse-options.h" -#include "repository.h" #include "commit-reach.h" static int show_merge_base(struct commit **rev, int rev_nr, int show_all) @@ -143,7 +143,10 @@ static int handle_fork_point(int argc, const char **argv) return 0; } -int cmd_merge_base(int argc, const char **argv, const char *prefix) +int cmd_merge_base(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct commit **rev; int rev_nr = 0; diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 1f987334a3..cb42865eb5 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "diff.h" @@ -53,7 +54,10 @@ static int diff_algorithm_cb(const struct option *opt, return 0; } -int cmd_merge_file(int argc, const char **argv, const char *prefix) +int cmd_merge_file(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *names[3] = { 0 }; mmfile_t mmfs[3] = { 0 }; diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 0fabe3f6bb..a5b87ee3c5 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "hex.h" #include "read-cache-ll.h" -#include "repository.h" #include "run-command.h" #include "sparse-index.h" @@ -73,7 +73,10 @@ static void merge_all(void) } } -int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_index(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i, force_file = 0; diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c index 932924e5d0..1fcf53f005 100644 --- a/builtin/merge-ours.c +++ b/builtin/merge-ours.c @@ -7,15 +7,19 @@ * * Pretend we resolved the heads, but declare our tree trumps everybody else. */ +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "builtin.h" #include "diff.h" -#include "repository.h" + static const char builtin_merge_ours_usage[] = "git merge-ours <base>... -- HEAD <remote>..."; -int cmd_merge_ours(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_ours(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { if (argc == 2 && !strcmp(argv[1], "-h")) usage(builtin_merge_ours_usage); diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 82bebea15b..1dd295558b 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "gettext.h" #include "hash.h" #include "merge-recursive.h" #include "object-name.h" -#include "repository.h" static const char builtin_merge_recursive_usage[] = "git %s <base>... -- <head> <remote> ..."; @@ -21,7 +21,10 @@ static char *better_branch_name(const char *branch) return xstrdup(name ? name : branch); } -int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_recursive(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { struct object_id bases[21]; unsigned bases_count = 0; @@ -31,7 +34,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED) char *better1, *better2; struct commit *result; - init_merge_options(&o, the_repository); + init_basic_merge_options(&o, the_repository); if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index dab2fdc2a6..c5ed472967 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "tree-walk.h" #include "xdiff-interface.h" @@ -10,7 +11,6 @@ #include "object-name.h" #include "object-store-ll.h" #include "parse-options.h" -#include "repository.h" #include "blob.h" #include "merge-blobs.h" #include "quote.h" @@ -526,13 +526,17 @@ static int real_merge(struct merge_tree_options *o, return !result.clean; /* result.clean < 0 handled above */ } -int cmd_merge_tree(int argc, const char **argv, const char *prefix) +int cmd_merge_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct merge_tree_options o = { .show_messages = -1 }; struct strvec xopts = STRVEC_INIT; int expected_remaining_argc; int original_argc; const char *merge_base = NULL; + int ret; const char * const merge_tree_usage[] = { N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), @@ -571,7 +575,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) }; /* Init merge options */ - init_merge_options(&o.merge_options, the_repository); + init_ui_merge_options(&o.merge_options, the_repository); /* Parse arguments */ original_argc = argc - 1; /* ignoring argv[0] */ @@ -625,7 +629,9 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) strbuf_list_free(split); } strbuf_release(&buf); - return 0; + + ret = 0; + goto out; } /* Figure out which mode to use */ @@ -664,7 +670,11 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) /* Do the relevant type of merge */ if (o.mode == MODE_REAL) - return real_merge(&o, merge_base, argv[0], argv[1], prefix); + ret = real_merge(&o, merge_base, argv[0], argv[1], prefix); else - return trivial_merge(argv[0], argv[1], argv[2]); + ret = trivial_merge(argv[0], argv[1], argv[2]); + +out: + strvec_clear(&xopts); + return ret; } diff --git a/builtin/merge.c b/builtin/merge.c index 9fba27d85d..e32c99087f 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -5,8 +5,9 @@ * * Based on git-merge.sh by Junio C Hamano. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "advice.h" #include "config.h" @@ -17,6 +18,7 @@ #include "object-name.h" #include "parse-options.h" #include "lockfile.h" +#include "repository.h" #include "run-command.h" #include "hook.h" #include "diff.h" @@ -478,7 +480,7 @@ static void finish(struct commit *head_commit, } /* Run a post-merge hook */ - run_hooks_l("post-merge", squash ? "1" : "0", NULL); + run_hooks_l(the_repository, "post-merge", squash ? "1" : "0", NULL); if (new_head) apply_autostash_ref(the_repository, "MERGE_AUTOSTASH"); @@ -496,7 +498,7 @@ static void merge_name(const char *remote, struct strbuf *msg) char *found_ref = NULL; int len, early; - strbuf_branchname(&bname, remote, 0); + copy_branchname(&bname, remote, 0); remote = bname.buf; oidclr(&branch_head, the_repository->hash_algo); @@ -695,7 +697,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head, static void write_tree_trivial(struct object_id *oid) { - if (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(oid, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) die(_("git write-tree failed to write a tree")); } @@ -724,7 +728,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, return 2; } - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; @@ -750,6 +754,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, clean = merge_recursive(&o, head, remoteheads->item, reversed, &result); free_commit_list(reversed); + strbuf_release(&o.obuf); if (clean < 0) { rollback_lock_file(&lock); @@ -757,7 +762,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, } if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write %s"), get_index_file()); + die(_("unable to write %s"), repo_get_index_file(the_repository)); return clean ? 0 : 1; } else { return try_merge_command(the_repository, @@ -839,7 +844,7 @@ static void write_merge_heads(struct commit_list *); static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; - const char *index_file = get_index_file(); + const char *index_file = repo_get_index_file(the_repository); if (!no_verify) { int invoked_hook; @@ -855,7 +860,8 @@ static void prepare_to_commit(struct commit_list *remoteheads) if (invoked_hook) discard_index(the_repository->index); } - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, + repo_get_git_dir(the_repository)); strbuf_addbuf(&msg, &merge_msg); if (squash) BUG("the control must not reach here under --squash"); @@ -878,8 +884,8 @@ static void prepare_to_commit(struct commit_list *remoteheads) append_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0); write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); - if (run_commit_hook(0 < option_edit, get_index_file(), NULL, - "prepare-commit-msg", + if (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository), + NULL, "prepare-commit-msg", git_path_merge_msg(the_repository), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { @@ -887,7 +893,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) abort_commit(remoteheads, NULL); } - if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), + if (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository), NULL, "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); @@ -1275,7 +1281,10 @@ static int merging_a_throwaway_tag(struct commit *commit) return is_throwaway_tag; } -int cmd_merge(int argc, const char **argv, const char *prefix) +int cmd_merge(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct object_id result_tree, stash, head_oid; struct commit *head_commit; @@ -1347,7 +1356,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) REF_NO_DEREF); /* Invoke 'git reset --merge' */ - ret = cmd_reset(nargc, nargv, prefix); + ret = cmd_reset(nargc, nargv, prefix, the_repository); if (!is_null_oid(&stash_oid)) { oid_to_hex_r(stash_oid_hex, &stash_oid); @@ -1379,7 +1388,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) die(_("There is no merge in progress (MERGE_HEAD missing).")); /* Invoke 'git commit' */ - ret = cmd_commit(nargc, nargv, prefix); + ret = cmd_commit(nargc, nargv, prefix, the_repository); goto done; } diff --git a/builtin/mktag.c b/builtin/mktag.c index 4767f1a97e..6e188dce50 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -18,8 +19,7 @@ static int option_strict = 1; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static int mktag_fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid UNUSED, - enum object_type object_type UNUSED, + void *fsck_report UNUSED, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id UNUSED, const char *message) @@ -72,7 +72,10 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) return ret; } -int cmd_mktag(int argc, const char **argv, const char *prefix) +int cmd_mktag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_mktag_options[] = { OPT_BOOL(0, "strict", &option_strict, diff --git a/builtin/mktree.c b/builtin/mktree.c index 9a22d4e277..3c16faa40e 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -3,6 +3,7 @@ * * Copyright (c) Junio C Hamano, 2006, 2009 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -150,7 +151,10 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing) free(to_free); } -int cmd_mktree(int ac, const char **av, const char *prefix) +int cmd_mktree(int ac, + const char **av, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf sb = STRBUF_INIT; struct object_id oid; @@ -199,5 +203,6 @@ int cmd_mktree(int ac, const char **av, const char *prefix) used=0; /* reset tree entry buffer for re-use in batch mode */ } strbuf_release(&sb); + return 0; } diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c index 9cf1a32d65..2a938466f5 100644 --- a/builtin/multi-pack-index.c +++ b/builtin/multi-pack-index.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "parse-options.h" #include "midx.h" @@ -9,6 +9,7 @@ #include "trace2.h" #include "object-store-ll.h" #include "replace-object.h" +#include "repository.h" #define BUILTIN_MIDX_WRITE_USAGE \ N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \ @@ -63,7 +64,7 @@ static int parse_object_dir(const struct option *opt, const char *arg, char **value = opt->value; free(*value); if (unset) - *value = xstrdup(get_object_directory()); + *value = xstrdup(repo_get_object_directory(the_repository)); else *value = real_pathdup(arg, 1); return 0; @@ -118,7 +119,8 @@ static void read_packs_from_stdin(struct string_list *to) } static int cmd_multi_pack_index_write(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo) { struct option *options; static struct option builtin_multi_pack_index_write_options[] = { @@ -129,6 +131,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX), OPT_BIT(0, "progress", &opts.flags, N_("force progress reporting"), MIDX_PROGRESS), + OPT_BIT(0, "incremental", &opts.flags, + N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL), OPT_BOOL(0, "stdin-packs", &opts.stdin_packs, N_("write multi-pack index containing only given indexes")), OPT_FILENAME(0, "refs-snapshot", &opts.refs_snapshot, @@ -161,7 +165,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, read_packs_from_stdin(&packs); - ret = write_midx_file_only(opts.object_dir, &packs, + ret = write_midx_file_only(repo, opts.object_dir, &packs, opts.preferred_pack, opts.refs_snapshot, opts.flags); @@ -172,7 +176,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, } - ret = write_midx_file(opts.object_dir, opts.preferred_pack, + ret = write_midx_file(repo, opts.object_dir, opts.preferred_pack, opts.refs_snapshot, opts.flags); free(opts.refs_snapshot); @@ -180,7 +184,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, } static int cmd_multi_pack_index_verify(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo UNUSED) { struct option *options; static struct option builtin_multi_pack_index_verify_options[] = { @@ -207,7 +212,8 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv, } static int cmd_multi_pack_index_expire(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo UNUSED) { struct option *options; static struct option builtin_multi_pack_index_expire_options[] = { @@ -234,7 +240,8 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv, } static int cmd_multi_pack_index_repack(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo UNUSED) { struct option *options; static struct option builtin_multi_pack_index_repack_options[] = { @@ -265,8 +272,10 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv, (size_t)opts.batch_size, opts.flags); } -int cmd_multi_pack_index(int argc, const char **argv, - const char *prefix) +int cmd_multi_pack_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { int res; parse_opt_subcommand_fn *fn = NULL; @@ -292,7 +301,7 @@ int cmd_multi_pack_index(int argc, const char **argv, builtin_multi_pack_index_usage, 0); FREE_AND_NULL(options); - res = fn(argc, argv, prefix); + res = fn(argc, argv, prefix, repo); free(opts.object_dir); return res; diff --git a/builtin/mv.c b/builtin/mv.c index 6c69033c5f..472a278737 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -3,6 +3,7 @@ * * Copyright (C) 2006 Johannes Schindelin */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" @@ -18,7 +19,7 @@ #include "string-list.h" #include "parse-options.h" #include "read-cache-ll.h" -#include "repository.h" + #include "setup.h" #include "strvec.h" #include "submodule.h" @@ -178,7 +179,10 @@ static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr) strbuf_release(&a_src_dir); } -int cmd_mv(int argc, const char **argv, const char *prefix) +int cmd_mv(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, flags, gitmodules_modified = 0; int verbose = 0, show_only = 0, force = 0, ignore_errors = 0, ignore_sparse = 0; diff --git a/builtin/name-rev.c b/builtin/name-rev.c index f62c0a36cb..765eb20a93 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "commit.h" #include "tag.h" @@ -65,7 +65,7 @@ static void set_commit_cutoff(struct commit *commit) static void adjust_cutoff_timestamp_for_slop(void) { if (cutoff) { - /* check for undeflow */ + /* check for underflow */ if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP) cutoff = cutoff - CUTOFF_DATE_SLOP; else @@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_) return a->taggerdate != b->taggerdate; } -static int name_ref(const char *path, const struct object_id *oid, +static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { struct object *o = parse_object(the_repository, oid); @@ -558,7 +558,10 @@ static void name_rev_line(char *p, struct name_ref_data *data) strbuf_release(&buf); } -int cmd_name_rev(int argc, const char **argv, const char *prefix) +int cmd_name_rev(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct mem_pool string_pool; struct object_array revs = OBJECT_ARRAY_INIT; diff --git a/builtin/notes.c b/builtin/notes.c index d9c356e354..d051abf6df 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -6,7 +6,7 @@ * Based on git-notes.sh by Johannes Schindelin, * and builtin/tag.c by Kristian Høgsberg and Carlos Rica. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "editor.h" @@ -17,7 +17,7 @@ #include "object-name.h" #include "object-store-ll.h" #include "path.h" -#include "repository.h" + #include "pretty.h" #include "refs.h" #include "exec-cmd.h" @@ -32,9 +32,9 @@ static const char *separator = "\n"; static const char * const git_notes_usage[] = { N_("git notes [--ref <notes-ref>] [list [<object>]]"), - N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), + N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>] [-e]"), N_("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"), - N_("git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), + N_("git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>] [-e]"), N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"), N_("git notes [--ref <notes-ref>] show [<object>]"), N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"), @@ -114,7 +114,6 @@ struct note_msg { }; struct note_data { - int given; int use_editor; int stripspace; char *edit_path; @@ -193,7 +192,7 @@ static void write_commented_object(int fd, const struct object_id *object) static void prepare_note_data(const struct object_id *object, struct note_data *d, const struct object_id *old_note) { - if (d->use_editor || !d->given) { + if (d->use_editor || !d->msg_nr) { int fd; struct strbuf buf = STRBUF_INIT; @@ -201,7 +200,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * d->edit_path = git_pathdup("NOTES_EDITMSG"); fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); - if (d->given) + if (d->msg_nr) write_or_die(fd, d->buf.buf, d->buf.len); else if (old_note) copy_obj_to_fd(fd, old_note); @@ -432,7 +431,8 @@ static struct notes_tree *init_notes_check(const char *subcommand, return t; } -static int list(int argc, const char **argv, const char *prefix) +static int list(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct notes_tree *t; struct object_id object; @@ -469,9 +469,11 @@ static int list(int argc, const char **argv, const char *prefix) return retval; } -static int append_edit(int argc, const char **argv, const char *prefix); +static int append_edit(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED); -static int add(int argc, const char **argv, const char *prefix) +static int add(int argc, const char **argv, const char *prefix, + struct repository *repo) { int force = 0, allow_empty = 0; const char *object_ref; @@ -490,6 +492,8 @@ static int add(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F('c', "reedit-message", &d, N_("object"), N_("reuse and edit specified note object"), PARSE_OPT_NONEG, parse_reedit_arg), + OPT_BOOL('e', "edit", &d.use_editor, + N_("edit note message in editor")), OPT_CALLBACK_F('C', "reuse-message", &d, N_("object"), N_("reuse specified note object"), PARSE_OPT_NONEG, parse_reuse_arg), @@ -515,7 +519,6 @@ static int add(int argc, const char **argv, const char *prefix) if (d.msg_nr) concat_messages(&d); - d.given = !!d.buf.len; object_ref = argc > 1 ? argv[1] : "HEAD"; @@ -528,7 +531,7 @@ static int add(int argc, const char **argv, const char *prefix) if (note) { if (!force) { free_notes(t); - if (d.given) { + if (d.msg_nr) { free_note_data(&d); return error(_("Cannot add notes. " "Found existing notes for object %s. " @@ -543,7 +546,7 @@ static int add(int argc, const char **argv, const char *prefix) * argv[0-1]. */ argv[0] = "edit"; - return append_edit(argc, argv, prefix); + return append_edit(argc, argv, prefix, repo); } fprintf(stderr, _("Overwriting existing notes for object %s\n"), oid_to_hex(&object)); @@ -569,7 +572,8 @@ static int add(int argc, const char **argv, const char *prefix) return 0; } -static int copy(int argc, const char **argv, const char *prefix) +static int copy(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int retval = 0, force = 0, from_stdin = 0; const struct object_id *from_note, *note; @@ -646,7 +650,8 @@ out: return retval; } -static int append_edit(int argc, const char **argv, const char *prefix) +static int append_edit(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int allow_empty = 0; const char *object_ref; @@ -669,6 +674,8 @@ static int append_edit(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F('C', "reuse-message", &d, N_("object"), N_("reuse specified note object"), PARSE_OPT_NONEG, parse_reuse_arg), + OPT_BOOL('e', "edit", &d.use_editor, + N_("edit note message in editor")), OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), OPT_CALLBACK_F(0, "separator", &separator, @@ -690,14 +697,14 @@ static int append_edit(int argc, const char **argv, const char *prefix) usage_with_options(usage, options); } - if (d.msg_nr) + if (d.msg_nr) { concat_messages(&d); - d.given = !!d.buf.len; - - if (d.given && edit) - fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated " - "for the 'edit' subcommand.\n" - "Please use 'git notes add -f -m/-F/-c/-C' instead.\n")); + if (edit) + fprintf(stderr, _("The -m/-F/-c/-C options have been " + "deprecated for the 'edit' subcommand.\n" + "Please use 'git notes add -f -m/-F/-c/-C' " + "instead.\n")); + } object_ref = 1 < argc ? argv[1] : "HEAD"; @@ -747,7 +754,8 @@ static int append_edit(int argc, const char **argv, const char *prefix) return 0; } -static int show(int argc, const char **argv, const char *prefix) +static int show(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { const char *object_ref; struct notes_tree *t; @@ -807,7 +815,7 @@ static int merge_commit(struct notes_merge_options *o) { struct strbuf msg = STRBUF_INIT; struct object_id oid, parent_oid; - struct notes_tree *t; + struct notes_tree t = {0}; struct commit *partial; struct pretty_print_context pretty_ctx; void *local_ref_to_free; @@ -830,8 +838,7 @@ static int merge_commit(struct notes_merge_options *o) else oidclr(&parent_oid, the_repository->hash_algo); - CALLOC_ARRAY(t, 1); - init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); + init_notes(&t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); o->local_ref = local_ref_to_free = refs_resolve_refdup(get_main_ref_store(the_repository), @@ -839,7 +846,7 @@ static int merge_commit(struct notes_merge_options *o) if (!o->local_ref) die(_("failed to resolve NOTES_MERGE_REF")); - if (notes_merge_commit(o, t, partial, &oid)) + if (notes_merge_commit(o, &t, partial, &oid)) die(_("failed to finalize notes merge")); /* Reuse existing commit message in reflog message */ @@ -853,7 +860,7 @@ static int merge_commit(struct notes_merge_options *o) is_null_oid(&parent_oid) ? NULL : &parent_oid, 0, UPDATE_REFS_DIE_ON_ERR); - free_notes(t); + free_notes(&t); strbuf_release(&msg); ret = merge_abort(o); free(local_ref_to_free); @@ -868,13 +875,14 @@ static int git_config_get_notes_strategy(const char *key, if (git_config_get_string(key, &value)) return 1; if (parse_notes_merge_strategy(value, strategy)) - git_die_config(key, _("unknown notes merge strategy %s"), value); + git_die_config(the_repository, key, _("unknown notes merge strategy %s"), value); free(value); return 0; } -static int merge(int argc, const char **argv, const char *prefix) +static int merge(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; struct object_id result_oid; @@ -900,6 +908,7 @@ static int merge(int argc, const char **argv, const char *prefix) 1, PARSE_OPT_NONEG), OPT_END() }; + char *notes_ref; argc = parse_options(argc, argv, prefix, options, git_notes_merge_usage, 0); @@ -927,7 +936,8 @@ static int merge(int argc, const char **argv, const char *prefix) if (do_commit) return merge_commit(&o); - o.local_ref = default_notes_ref(); + notes_ref = default_notes_ref(the_repository); + o.local_ref = notes_ref; strbuf_addstr(&remote_ref, argv[0]); expand_loose_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; @@ -956,7 +966,7 @@ static int merge(int argc, const char **argv, const char *prefix) } strbuf_addf(&msg, "notes: Merged notes from %s into %s", - remote_ref.buf, default_notes_ref()); + remote_ref.buf, notes_ref); strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ result = notes_merge(&o, t, &result_oid); @@ -964,7 +974,7 @@ static int merge(int argc, const char **argv, const char *prefix) if (result >= 0) /* Merge resulted (trivially) in result_oid */ /* Update default notes ref with new commit */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, - default_notes_ref(), &result_oid, NULL, 0, + notes_ref, &result_oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ struct worktree **worktrees; @@ -976,14 +986,14 @@ static int merge(int argc, const char **argv, const char *prefix) /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ worktrees = get_worktrees(); wt = find_shared_symref(worktrees, "NOTES_MERGE_REF", - default_notes_ref()); + notes_ref); if (wt) die(_("a notes merge into %s is already in-progress at %s"), - default_notes_ref(), wt->path); + notes_ref, wt->path); free_worktrees(worktrees); - if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL)) + 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)"), - default_notes_ref()); + notes_ref); 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"), @@ -991,6 +1001,7 @@ static int merge(int argc, const char **argv, const char *prefix) } free_notes(t); + free(notes_ref); strbuf_release(&remote_ref); strbuf_release(&msg); return result < 0; /* return non-zero on conflicts */ @@ -1012,7 +1023,8 @@ static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag return (flag & IGNORE_MISSING) ? 0 : status; } -static int remove_cmd(int argc, const char **argv, const char *prefix) +static int remove_cmd(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { unsigned flag = 0; int from_stdin = 0; @@ -1055,7 +1067,8 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) return retval; } -static int prune(int argc, const char **argv, const char *prefix) +static int prune(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct notes_tree *t; int show_only = 0, verbose = 0; @@ -1084,9 +1097,11 @@ static int prune(int argc, const char **argv, const char *prefix) return 0; } -static int get_ref(int argc, const char **argv, const char *prefix) +static int get_ref(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() }; + char *notes_ref; argc = parse_options(argc, argv, prefix, options, git_notes_get_ref_usage, 0); @@ -1095,11 +1110,16 @@ static int get_ref(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_get_ref_usage, options); } - puts(default_notes_ref()); + notes_ref = default_notes_ref(the_repository); + puts(notes_ref); + free(notes_ref); return 0; } -int cmd_notes(int argc, const char **argv, const char *prefix) +int cmd_notes(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { const char *override_notes_ref = NULL; parse_opt_subcommand_fn *fn = NULL; @@ -1138,5 +1158,5 @@ int cmd_notes(int argc, const char **argv, const char *prefix) strbuf_release(&sb); } - return !!fn(argc, argv, prefix); + return !!fn(argc, argv, prefix, repo); } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index f395488971..7dc51c03c4 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "attr.h" #include "object.h" @@ -239,6 +239,7 @@ static enum { static uint16_t write_bitmap_options = BITMAP_OPT_HASH_CACHE; static int exclude_promisor_objects; +static int exclude_promisor_objects_best_effort; static int use_delta_islands; @@ -771,7 +772,7 @@ static enum write_one_status write_one(struct hashfile *f, return WRITE_ONE_WRITTEN; } -static int mark_tagged(const char *path UNUSED, const struct object_id *oid, +static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id peeled; @@ -1072,7 +1073,7 @@ static void write_reused_pack_one(struct packed_git *reuse_packfile, fixup = find_reused_offset(offset) - find_reused_offset(base_offset); if (fixup) { - unsigned char ofs_header[10]; + unsigned char ofs_header[MAX_PACK_OBJECT_HEADER]; unsigned i, ofs_len; off_t ofs = offset - base_offset - fixup; @@ -1100,78 +1101,64 @@ static void write_reused_pack_one(struct packed_git *reuse_packfile, static size_t write_reused_pack_verbatim(struct bitmapped_pack *reuse_packfile, struct hashfile *out, - off_t pack_start, struct pack_window **w_curs) { - size_t pos = reuse_packfile->bitmap_pos; + size_t pos = 0; size_t end; - if (pos % BITS_IN_EWORD) { - size_t word_pos = (pos / BITS_IN_EWORD); - size_t offset = pos % BITS_IN_EWORD; - size_t last; - eword_t word = reuse_packfile_bitmap->words[word_pos]; - - if (offset + reuse_packfile->bitmap_nr < BITS_IN_EWORD) - last = offset + reuse_packfile->bitmap_nr; - else - last = BITS_IN_EWORD; - - for (; offset < last; offset++) { - if (word >> offset == 0) - return word_pos; - if (!bitmap_get(reuse_packfile_bitmap, - word_pos * BITS_IN_EWORD + offset)) - return word_pos; - } - - pos += BITS_IN_EWORD - (pos % BITS_IN_EWORD); + if (reuse_packfile->bitmap_pos) { + /* + * We can't reuse whole chunks verbatim out of + * non-preferred packs since we can't guarantee that + * all duplicate objects were resolved in favor of + * that pack. + * + * Even if we have a whole eword_t worth of bits that + * could be reused, there may be objects between the + * objects corresponding to the first and last bit of + * that word which were selected from a different + * pack, causing us to send duplicate or unwanted + * objects. + * + * Handle non-preferred packs from within + * write_reused_pack(), which inspects and reuses + * individual bits. + */ + return reuse_packfile->bitmap_pos / BITS_IN_EWORD; } /* - * Now we're going to copy as many whole eword_t's as possible. - * "end" is the index of the last whole eword_t we copy, but - * there may be additional bits to process. Those are handled - * individually by write_reused_pack(). + * Only read through the last word whose bits all correspond + * to objects in the given packfile, since we must stop at a + * word boundary. * - * Begin by advancing to the first word boundary in range of the - * bit positions occupied by objects in "reuse_packfile". Then - * pick the last word boundary in the same range. If we have at - * least one word's worth of bits to process, continue on. + * If there is no whole word to read (i.e. the packfile + * contains fewer than BITS_IN_EWORD objects), then we'll + * inspect bits one-by-one in write_reused_pack(). */ - end = reuse_packfile->bitmap_pos + reuse_packfile->bitmap_nr; - if (end % BITS_IN_EWORD) - end -= end % BITS_IN_EWORD; - if (pos >= end) - return reuse_packfile->bitmap_pos / BITS_IN_EWORD; + end = reuse_packfile->bitmap_nr / BITS_IN_EWORD; + if (reuse_packfile_bitmap->word_alloc < end) + BUG("fewer words than expected in reuse_packfile_bitmap"); - while (pos < end && - reuse_packfile_bitmap->words[pos / BITS_IN_EWORD] == (eword_t)~0) - pos += BITS_IN_EWORD; + while (pos < end && reuse_packfile_bitmap->words[pos] == (eword_t)~0) + pos++; - if (pos > end) - pos = end; + if (pos) { + off_t to_write; - if (reuse_packfile->bitmap_pos < pos) { - off_t pack_start_off = pack_pos_to_offset(reuse_packfile->p, 0); - off_t pack_end_off = pack_pos_to_offset(reuse_packfile->p, - pos - reuse_packfile->bitmap_pos); - - written += pos - reuse_packfile->bitmap_pos; + written = (pos * BITS_IN_EWORD); + to_write = pack_pos_to_offset(reuse_packfile->p, written) + - sizeof(struct pack_header); /* We're recording one chunk, not one object. */ - record_reused_object(pack_start_off, - pack_start_off - (hashfile_total(out) - pack_start)); + record_reused_object(sizeof(struct pack_header), 0); hashflush(out); copy_pack_data(out, reuse_packfile->p, w_curs, - pack_start_off, pack_end_off - pack_start_off); + sizeof(struct pack_header), to_write); display_progress(progress_state, written); } - if (pos % BITS_IN_EWORD) - BUG("attempted to jump past a word boundary to %"PRIuMAX, - (uintmax_t)pos); - return pos / BITS_IN_EWORD; + return pos; } static void write_reused_pack(struct bitmapped_pack *reuse_packfile, @@ -1183,14 +1170,14 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile, struct pack_window *w_curs = NULL; if (allow_ofs_delta) - i = write_reused_pack_verbatim(reuse_packfile, f, pack_start, - &w_curs); + i = write_reused_pack_verbatim(reuse_packfile, f, &w_curs); for (; i < reuse_packfile_bitmap->word_alloc; ++i) { eword_t word = reuse_packfile_bitmap->words[i]; size_t pos = (i * BITS_IN_EWORD); for (offset = 0; offset < BITS_IN_EWORD; ++offset) { + uint32_t pack_pos; if ((word >> offset) == 0) break; @@ -1199,14 +1186,41 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile, continue; if (pos + offset >= reuse_packfile->bitmap_pos + reuse_packfile->bitmap_nr) goto done; - /* - * Can use bit positions directly, even for MIDX - * bitmaps. See comment in try_partial_reuse() - * for why. - */ - write_reused_pack_one(reuse_packfile->p, - pos + offset - reuse_packfile->bitmap_pos, - f, pack_start, &w_curs); + + if (reuse_packfile->bitmap_pos) { + /* + * When doing multi-pack reuse on a + * non-preferred pack, translate bit positions + * from the MIDX pseudo-pack order back to their + * pack-relative positions before attempting + * reuse. + */ + struct multi_pack_index *m = reuse_packfile->from_midx; + uint32_t midx_pos; + off_t pack_ofs; + + if (!m) + BUG("non-zero bitmap position without MIDX"); + + midx_pos = pack_pos_to_midx(m, pos + offset); + pack_ofs = nth_midxed_offset(m, midx_pos); + + if (offset_to_pack_pos(reuse_packfile->p, + pack_ofs, &pack_pos) < 0) + BUG("could not find expected object at offset %"PRIuMAX" in pack %s", + (uintmax_t)pack_ofs, + pack_basename(reuse_packfile->p)); + } else { + /* + * Can use bit positions directly, even for MIDX + * bitmaps. See comment in try_partial_reuse() + * for why. + */ + pack_pos = pos + offset; + } + + write_reused_pack_one(reuse_packfile->p, pack_pos, f, + pack_start, &w_curs); display_progress(progress_state, ++written); } } @@ -1342,10 +1356,10 @@ static void write_pack_file(void) if (write_bitmap_index) { bitmap_writer_init(&bitmap_writer, - the_repository); + the_repository, &to_pack); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, - &to_pack, written_list, nr_written); + written_list); } if (cruft) @@ -1367,10 +1381,10 @@ static void write_pack_file(void) bitmap_writer_select_commits(&bitmap_writer, indexed_commits, indexed_commits_nr); - if (bitmap_writer_build(&bitmap_writer, &to_pack) < 0) + if (bitmap_writer_build(&bitmap_writer) < 0) die(_("failed to write bitmap index")); bitmap_writer_finish(&bitmap_writer, - written_list, nr_written, + written_list, tmpname.buf, write_bitmap_options); bitmap_writer_free(&bitmap_writer); write_bitmap_index = 0; @@ -1501,7 +1515,7 @@ static int want_found_object(const struct object_id *oid, int exclude, return 0; if (ignore_packed_keep_in_core && p->pack_keep_in_core) return 0; - if (has_object_kept_pack(oid, flags)) + if (has_object_kept_pack(p->repo, oid, flags)) return 0; } @@ -1528,7 +1542,7 @@ static int want_object_in_pack_one(struct packed_git *p, if (p == *found_pack) offset = *found_offset; else - offset = find_pack_entry_one(oid->hash, p); + offset = find_pack_entry_one(oid, p); if (offset) { if (!*found_pack) { @@ -3129,7 +3143,7 @@ static void add_tag_chain(const struct object_id *oid) } } -static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid, +static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id peeled; @@ -3599,7 +3613,7 @@ static void show_cruft_commit(struct commit *commit, void *data) static int cruft_include_check_obj(struct object *obj, void *data UNUSED) { - return !has_object_kept_pack(&obj->oid, IN_CORE_KEEP_PACKS); + return !has_object_kept_pack(to_pack.repo, &obj->oid, IN_CORE_KEEP_PACKS); } static int cruft_include_check(struct commit *commit, void *data) @@ -3830,7 +3844,8 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, * Quietly ignore EXPECTED missing objects. This avoids problems with * staging them now and getting an odd error later. */ - if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) + if (!has_object(the_repository, &obj->oid, 0) && + is_promisor_object(to_pack.repo, &obj->oid)) return; show_object(obj, name, data); @@ -3899,7 +3914,9 @@ static int add_object_in_unpacked_pack(const struct object_id *oid, static void add_objects_in_unpacked_packs(void) { - if (for_each_packed_object(add_object_in_unpacked_pack, NULL, + if (for_each_packed_object(to_pack.repo, + add_object_in_unpacked_pack, + NULL, FOR_EACH_OBJECT_PACK_ORDER | FOR_EACH_OBJECT_LOCAL_ONLY | FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS | @@ -3940,7 +3957,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, */ static void add_unreachable_loose_objects(void) { - for_each_loose_file_in_objdir(get_object_directory(), + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), add_loose_object, NULL, NULL, NULL); } @@ -3956,7 +3973,7 @@ static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid) while (p) { if ((!p->pack_local || p->pack_keep || p->pack_keep_in_core) && - find_pack_entry_one(oid->hash, p)) { + find_pack_entry_one(oid, p)) { last_found = p; return 1; } @@ -4076,6 +4093,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED) } static int mark_bitmap_preferred_tip(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *data UNUSED) @@ -4283,7 +4301,22 @@ static int option_parse_cruft_expiration(const struct option *opt UNUSED, return 0; } -int cmd_pack_objects(int argc, const char **argv, const char *prefix) +static int is_not_in_promisor_pack_obj(struct object *obj, void *data UNUSED) +{ + struct object_info info = OBJECT_INFO_INIT; + if (oid_object_info_extended(the_repository, &obj->oid, &info, 0)) + BUG("should_include_obj should only be called on existing objects"); + return info.whence != OI_PACKED || !info.u.packed.pack->pack_promisor; +} + +static int is_not_in_promisor_pack(struct commit *commit, void *data) { + return is_not_in_promisor_pack_obj((struct object *) commit, data); +} + +int cmd_pack_objects(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int use_internal_rev_list = 0; int shallow = 0; @@ -4392,6 +4425,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) option_parse_missing_action), OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects, N_("do not pack objects in promisor packfiles")), + OPT_BOOL(0, "exclude-promisor-objects-best-effort", + &exclude_promisor_objects_best_effort, + N_("implies --missing=allow-any")), OPT_BOOL(0, "delta-islands", &use_delta_islands, N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, @@ -4472,10 +4508,18 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) strvec_push(&rp, "--unpacked"); } + if (exclude_promisor_objects && exclude_promisor_objects_best_effort) + die(_("options '%s' and '%s' cannot be used together"), + "--exclude-promisor-objects", "--exclude-promisor-objects-best-effort"); if (exclude_promisor_objects) { use_internal_rev_list = 1; fetch_if_missing = 0; strvec_push(&rp, "--exclude-promisor-objects"); + } else if (exclude_promisor_objects_best_effort) { + use_internal_rev_list = 1; + fetch_if_missing = 0; + option_parse_missing_action(NULL, "allow-any", 0); + /* revs configured below */ } if (unpack_unreachable || keep_unreachable || pack_loose_unreachable) use_internal_rev_list = 1; @@ -4595,6 +4639,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) repo_init_revisions(the_repository, &revs, NULL); list_objects_filter_copy(&revs.filter, &filter_options); + if (exclude_promisor_objects_best_effort) { + revs.include_check = is_not_in_promisor_pack; + revs.include_check_obj = is_not_in_promisor_pack_obj; + } get_object_list(&revs, rp.nr, rp.v); release_revisions(&revs); } @@ -4640,6 +4688,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) cleanup: clear_packing_data(&to_pack); list_objects_filter_release(&filter_options); + string_list_clear(&keep_pack_list, 0); strvec_clear(&rp); return 0; diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index dd9bf35f5b..bc61990a93 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -5,13 +5,15 @@ * This file is licensed under the GPL v2. * */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" -#include "repository.h" + #include "packfile.h" #include "object-store-ll.h" +#include "strbuf.h" #define BLKSIZE 512 @@ -68,6 +70,15 @@ static inline void llist_init(struct llist **list) (*list)->size = 0; } +static void llist_free(struct llist *list) +{ + for (struct llist_item *i = list->front, *next; i; i = next) { + next = i->next; + llist_item_put(i); + } + free(list); +} + static struct llist * llist_copy(struct llist *list) { struct llist *ret; @@ -205,6 +216,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl, return p; } +static void pack_list_free(struct pack_list *pl) +{ + for (struct pack_list *next; pl; pl = next) { + next = pl->next; + free(pl); + } +} + static inline size_t pack_list_size(struct pack_list *pl) { size_t ret = 0; @@ -418,7 +437,8 @@ static void minimize(struct pack_list **min) /* return if there are no objects missing from the unique set */ if (missing->size == 0) { - free(missing); + llist_free(missing); + pack_list_free(non_unique); return; } @@ -433,6 +453,8 @@ static void minimize(struct pack_list **min) } while (non_unique) { + struct pack_list *next; + /* sort the non_unique packs, greater size of remaining_objects first */ sort_pack_list(&non_unique); if (non_unique->remaining_objects->size == 0) @@ -443,8 +465,14 @@ static void minimize(struct pack_list **min) for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next) llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects); - non_unique = non_unique->next; + next = non_unique->next; + free(non_unique); + non_unique = next; } + + pack_list_free(non_unique); + llist_free(unique_pack_objects); + llist_free(missing); } static void load_all_objects(void) @@ -561,13 +589,10 @@ static void load_all(void) } } -int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) -{ - int i; - int i_still_use_this = 0; - struct pack_list *min = NULL, *red, *pl; +int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { + int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl; struct llist *ignore; - struct object_id *oid; + struct strbuf idx_name = STRBUF_INIT; char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ if (argc == 2 && !strcmp(argv[1], "-h")) @@ -627,11 +652,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) /* ignore objects given on stdin */ llist_init(&ignore); if (!isatty(0)) { + struct object_id oid; while (fgets(buf, sizeof(buf), stdin)) { - oid = xmalloc(sizeof(*oid)); - if (get_oid_hex(buf, oid)) + if (get_oid_hex(buf, &oid)) die("Bad object ID on stdin: %s", buf); - llist_insert_sorted_unique(ignore, oid, NULL); + llist_insert_sorted_unique(ignore, &oid, NULL); } } llist_sorted_difference_inplace(all_objects, ignore); @@ -665,7 +690,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) pl = red = pack_list_difference(local_packs, min); while (pl) { printf("%s\n%s\n", - sha1_pack_index_name(pl->pack->hash), + odb_pack_name(pl->pack->repo, &idx_name, pl->pack->hash, "idx"), pl->pack->pack_name); pl = pl->next; } @@ -673,5 +698,9 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) fprintf(stderr, "%luMB of redundant packs in total.\n", (unsigned long)pack_set_bytecount(red)/(1024*1024)); + pack_list_free(red); + pack_list_free(min); + llist_free(ignore); + strbuf_release(&idx_name); return 0; } diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index db40825666..2d83c1ed2a 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" #include "refs.h" -#include "repository.h" #include "revision.h" static char const * const pack_refs_usage[] = { @@ -11,7 +11,10 @@ static char const * const pack_refs_usage[] = { NULL }; -int cmd_pack_refs(int argc, const char **argv, const char *prefix) +int cmd_pack_refs(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; diff --git a/builtin/patch-id.c b/builtin/patch-id.c index d790ae6354..93b398e391 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" @@ -214,7 +215,10 @@ static int git_patch_id_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_patch_id(int argc, const char **argv, const char *prefix) +int cmd_patch_id(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { /* if nothing is set, default to unstable */ struct patch_id_opts config = {0, 0}; diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c index ca3578e158..4d63f26b0a 100644 --- a/builtin/prune-packed.c +++ b/builtin/prune-packed.c @@ -8,7 +8,10 @@ static const char * const prune_packed_usage[] = { NULL }; -int cmd_prune_packed(int argc, const char **argv, const char *prefix) +int cmd_prune_packed(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int opts = isatty(2) ? PRUNE_PACKED_VERBOSE : 0; const struct option prune_packed_options[] = { diff --git a/builtin/prune.c b/builtin/prune.c index 57fe31467f..2b1de01339 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "diff.h" @@ -147,7 +148,10 @@ static void remove_temporary_files(const char *path) closedir(dir); } -int cmd_prune(int argc, const char **argv, const char *prefix) +int cmd_prune(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; int exclude_promisor_objects = 0; @@ -193,12 +197,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix) revs.exclude_promisor_objects = 1; } - for_each_loose_file_in_objdir(get_object_directory(), prune_object, - prune_cruft, prune_subdir, &revs); + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), + prune_object, prune_cruft, prune_subdir, &revs); prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0); - remove_temporary_files(get_object_directory()); - s = mkpathdup("%s/pack", get_object_directory()); + remove_temporary_files(repo_get_object_directory(the_repository)); + s = mkpathdup("%s/pack", repo_get_object_directory(the_repository)); remove_temporary_files(s); free(s); diff --git a/builtin/pull.c b/builtin/pull.c index 4c54d8196f..edc56907aa 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -6,6 +6,7 @@ * Fetch one or more remote refs and merge it/them into the current HEAD. */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -84,7 +85,7 @@ static const char *opt_squash; static const char *opt_commit; static const char *opt_edit; static const char *cleanup_arg; -static const char *opt_ff; +static char *opt_ff; static const char *opt_verify_signatures; static const char *opt_verify; static int opt_autostash = -1; @@ -217,8 +218,8 @@ static struct option pull_options[] = { OPT_PASSTHRU_ARGV(0, "shallow-since", &opt_fetch, N_("time"), N_("deepen history of shallow repository based on time"), 0), - OPT_PASSTHRU_ARGV(0, "shallow-exclude", &opt_fetch, N_("revision"), - N_("deepen history of shallow clone, excluding rev"), + OPT_PASSTHRU_ARGV(0, "shallow-exclude", &opt_fetch, N_("ref"), + N_("deepen history of shallow clone, excluding ref"), 0), OPT_PASSTHRU_ARGV(0, "deepen", &opt_fetch, N_("n"), N_("deepen history of shallow clone"), @@ -977,7 +978,10 @@ static void show_advice_pull_non_ff(void) "invocation.\n")); } -int cmd_pull(int argc, const char **argv, const char *prefix) +int cmd_pull(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { const char *repo, **refspecs; struct oid_array merge_heads = OID_ARRAY_INIT; @@ -1024,8 +1028,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix) * "--rebase" can override a config setting of * pull.ff=only. */ - if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) - opt_ff = "--ff"; + if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) { + free(opt_ff); + opt_ff = xstrdup("--ff"); + } } if (opt_rebase < 0) @@ -1135,7 +1141,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (can_ff) { /* we can fast-forward this without invoking rebase */ - opt_ff = "--ff-only"; + free(opt_ff); + opt_ff = xstrdup("--ff-only"); ret = run_merge(); } else { ret = run_rebase(&newbase, &upstream); diff --git a/builtin/push.c b/builtin/push.c index 7a67398124..51c609f208 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -1,6 +1,7 @@ /* * "git push" */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "branch.h" @@ -13,7 +14,6 @@ #include "transport.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" #include "submodule.h" #include "submodule-config.h" #include "send-pack.h" @@ -72,13 +72,15 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref, const char *branch_name; if (remote->push.nr) { - struct refspec_item query; - memset(&query, 0, sizeof(struct refspec_item)); - query.src = matched->name; + struct refspec_item query = { + .src = matched->name, + }; + if (!query_refspecs(&remote->push, &query) && query.dst) { refspec_appendf(refspec, "%s%s:%s", query.force ? "+" : "", query.src, query.dst); + free(query.dst); return; } } @@ -517,14 +519,7 @@ static int git_push_config(const char *k, const char *v, RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF; recurse_submodules = val; } else if (!strcmp(k, "push.pushoption")) { - if (!v) - return config_error_nonbool(k); - else - if (!*v) - string_list_clear(&push_options_config, 0); - else - string_list_append(&push_options_config, v); - return 0; + return parse_transport_option(k, v, &push_options_config); } else if (!strcmp(k, "color.push")) { push_use_color = git_config_colorbool(k, v); return 0; @@ -546,7 +541,10 @@ static int git_push_config(const char *k, const char *v, return git_default_config(k, v, ctx, NULL); } -int cmd_push(int argc, const char **argv, const char *prefix) +int cmd_push(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { int flags = 0; int tags = 0; @@ -664,6 +662,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) rc = do_push(flags, push_options, remote); string_list_clear(&push_options_cmdline, 0); string_list_clear(&push_options_config, 0); + clear_cas_option(&cas); if (rc == -1) usage_with_options(push_usage, options); else diff --git a/builtin/range-diff.c b/builtin/range-diff.c index f02cbac087..1b33ab66a7 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -1,10 +1,11 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "object-name.h" #include "parse-options.h" #include "range-diff.h" #include "config.h" -#include "repository.h" + static const char * const builtin_range_diff_usage[] = { N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"), @@ -13,7 +14,10 @@ N_("git range-diff [<options>] <base> <old-tip> <new-tip>"), NULL }; -int cmd_range_diff(int argc, const char **argv, const char *prefix) +int cmd_range_diff(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct diff_options diffopt = { NULL }; struct strvec other_arg = STRVEC_INIT; diff --git a/builtin/read-tree.c b/builtin/read-tree.c index a8cf8504b8..d2a807a828 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -16,7 +16,6 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "parse-options.h" -#include "repository.h" #include "resolve-undo.h" #include "setup.h" #include "sparse-index.h" @@ -108,7 +107,10 @@ static int git_read_tree_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) +int cmd_read_tree(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int i, stage = 0; struct object_id oid; diff --git a/builtin/rebase.c b/builtin/rebase.c index e3a8e74cfc..bbaca3c5d5 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -3,8 +3,9 @@ * * Copyright (c) 2018 Pratik Karki */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "environment.h" #include "gettext.h" @@ -186,6 +187,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) replay.committer_date_is_author_date = opts->committer_date_is_author_date; replay.ignore_date = opts->ignore_date; + free(replay.gpg_sign); replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt); replay.reflog_action = xstrdup(opts->reflog_action); if (opts->strategy) @@ -526,6 +528,23 @@ static int rebase_write_basic_state(struct rebase_options *opts) return 0; } +static int cleanup_autostash(struct rebase_options *opts) +{ + int ret; + struct strbuf dir = STRBUF_INIT; + const char *path = state_dir_path("autostash", opts); + + if (!file_exists(path)) + return 0; + ret = apply_autostash(path); + strbuf_addstr(&dir, opts->state_dir); + if (remove_dir_recursively(&dir, 0)) + ret = error_errno(_("could not remove '%s'"), opts->state_dir); + strbuf_release(&dir); + + return ret; +} + static int finish_rebase(struct rebase_options *opts) { struct strbuf dir = STRBUF_INIT; @@ -1062,7 +1081,10 @@ static int check_exec_cmd(const char *cmd) return 0; } -int cmd_rebase(int argc, const char **argv, const char *prefix) +int cmd_rebase(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rebase_options options = REBASE_OPTIONS_INIT; const char *branch_name; @@ -1726,7 +1748,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (require_clean_work_tree(the_repository, "rebase", _("Please commit or stash them."), 1, 1)) { ret = -1; - goto cleanup; + goto cleanup_autostash; } /* @@ -1749,7 +1771,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (options.switch_to) { ret = checkout_up_to_date(&options); if (ret) - goto cleanup; + goto cleanup_autostash; } if (!(options.flags & REBASE_NO_QUIET)) @@ -1774,9 +1796,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) /* If a hook exists, give it a chance to interrupt*/ if (!ok_to_skip_pre_rebase && - run_hooks_l("pre-rebase", options.upstream_arg, - argc ? argv[0] : NULL, NULL)) - die(_("The pre-rebase hook refused to rebase.")); + run_hooks_l(the_repository, "pre-rebase", options.upstream_arg, + argc ? argv[0] : NULL, NULL)) { + ret = error(_("The pre-rebase hook refused to rebase.")); + goto cleanup_autostash; + } if (options.flags & REBASE_DIFFSTAT) { struct diff_options opts; @@ -1821,9 +1845,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) RESET_HEAD_RUN_POST_CHECKOUT_HOOK; ropts.head_msg = msg.buf; ropts.default_reflog_action = options.reflog_action; - if (reset_head(the_repository, &ropts)) - die(_("Could not detach HEAD")); - strbuf_release(&msg); + if (reset_head(the_repository, &ropts)) { + ret = error(_("Could not detach HEAD")); + goto cleanup_autostash; + } /* * If the onto is a proper descendant of the tip of the branch, then @@ -1851,9 +1876,14 @@ run_rebase: cleanup: strbuf_release(&buf); + strbuf_release(&msg); strbuf_release(&revisions); rebase_options_release(&options); free(squash_onto_name); free(keep_base_onto_name); return !!ret; + +cleanup_autostash: + ret |= !!cleanup_autostash(&options); + goto cleanup; } diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 339524ae2a..9d2c07f68d 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1,6 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" -#include "repository.h" + #include "config.h" #include "environment.h" #include "gettext.h" @@ -300,7 +301,7 @@ static void show_ref(const char *path, const struct object_id *oid) } } -static int show_ref_cb(const char *path_full, const struct object_id *oid, +static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *data) { struct oidset *seen = data; @@ -339,12 +340,26 @@ static void show_one_alternate_ref(const struct object_id *oid, static void write_head_info(void) { static struct oidset seen = OIDSET_INIT; + struct strvec excludes_vector = STRVEC_INIT; + const char **exclude_patterns; + + /* + * We need access to the reference names both with and without their + * namespace and thus cannot use `refs_for_each_namespaced_ref()`. We + * thus have to adapt exclude patterns to carry the namespace prefix + * ourselves. + */ + exclude_patterns = get_namespaced_exclude_patterns( + hidden_refs_to_excludes(&hidden_refs), + get_git_namespace(), &excludes_vector); refs_for_each_fullref_in(get_main_ref_store(the_repository), "", - hidden_refs_to_excludes(&hidden_refs), - show_ref_cb, &seen); + exclude_patterns, show_ref_cb, &seen); for_each_alternate_ref(show_one_alternate_ref, &seen); + oidset_clear(&seen); + strvec_clear(&excludes_vector); + if (!sent_capabilities) show_ref("capabilities^{}", null_oid()); @@ -359,6 +374,7 @@ static void write_head_info(void) struct command { struct command *next; const char *error_string; + char *error_string_owned; struct ref_push_report *report; unsigned int skip_update:1, did_not_exist:1, @@ -792,7 +808,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, struct child_process proc = CHILD_PROCESS_INIT; struct async muxer; int code; - const char *hook_path = find_hook(hook_name); + const char *hook_path = find_hook(the_repository, hook_name); if (!hook_path) return 0; @@ -922,7 +938,7 @@ static int run_update_hook(struct command *cmd) { struct child_process proc = CHILD_PROCESS_INIT; int code; - const char *hook_path = find_hook("update"); + const char *hook_path = find_hook(the_repository, "update"); if (!hook_path) return 0; @@ -1068,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader, hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED; if (!strcmp(head, "ng")) { if (p) - hint->error_string = xstrdup(p); + hint->error_string = hint->error_string_owned = xstrdup(p); else hint->error_string = "failed"; code = -1; @@ -1098,7 +1114,7 @@ static int run_proc_receive_hook(struct command *commands, int hook_use_push_options = 0; int version = 0; int code; - const char *hook_path = find_hook("proc-receive"); + const char *hook_path = find_hook(the_repository, "proc-receive"); if (!hook_path) { rp_error("cannot find hook 'proc-receive'"); @@ -1324,7 +1340,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) } /* - * NEEDSWORK: we should consolidate various implementions of "are we + * NEEDSWORK: we should consolidate various implementations of "are we * on an unborn branch?" test into one, and make the unified one more * robust. !get_sha1() based check used here and elsewhere would not * allow us to tell an unborn branch from corrupt ref, for example. @@ -1409,7 +1425,7 @@ static const char *push_to_checkout(unsigned char *hash, strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree)); strvec_pushv(&opt.env, env->v); strvec_push(&opt.args, hash_to_hex(hash)); - if (run_hooks_opt(push_to_checkout_hook, &opt)) + if (run_hooks_opt(the_repository, push_to_checkout_hook, &opt)) return "push-to-checkout hook declined"; else return NULL; @@ -1618,7 +1634,7 @@ static void run_update_post_hook(struct command *commands) struct child_process proc = CHILD_PROCESS_INIT; const char *hook; - hook = find_hook("post-update"); + hook = find_hook(the_repository, "post-update"); if (!hook) return; @@ -1833,7 +1849,7 @@ static void execute_commands_non_atomic(struct command *commands, continue; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { rp_error("%s", err.buf); strbuf_reset(&err); @@ -1862,7 +1878,7 @@ static void execute_commands_atomic(struct command *commands, const char *reported_error = "atomic push failure"; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { rp_error("%s", err.buf); strbuf_reset(&err); @@ -2039,6 +2055,8 @@ static void free_commands(struct command *commands) while (commands) { struct command *next = commands->next; + ref_push_report_free(commands->report); + free(commands->error_string_owned); free(commands); commands = next; } @@ -2480,7 +2498,10 @@ static int delete_only(struct command *commands) return 1; } -int cmd_receive_pack(int argc, const char **argv, const char *prefix) +int cmd_receive_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int advertise_refs = 0; struct command *commands; diff --git a/builtin/reflog.c b/builtin/reflog.c index 0d2ff95c6e..5a0c22f2f7 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" -#include "repository.h" #include "revision.h" #include "reachable.h" #include "wildmatch.h" @@ -234,7 +234,8 @@ static int expire_total_callback(const struct option *opt, return 0; } -static int cmd_reflog_show(int argc, const char **argv, const char *prefix) +static int cmd_reflog_show(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -244,7 +245,7 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); - return cmd_log_reflog(argc, argv, prefix); + return cmd_log_reflog(argc, argv, prefix, the_repository); } static int show_reflog(const char *refname, void *cb_data UNUSED) @@ -253,7 +254,8 @@ static int show_reflog(const char *refname, void *cb_data UNUSED) return 0; } -static int cmd_reflog_list(int argc, const char **argv, const char *prefix) +static int cmd_reflog_list(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -270,7 +272,8 @@ static int cmd_reflog_list(int argc, const char **argv, const char *prefix) return refs_for_each_reflog(ref_store, show_reflog, NULL); } -static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) +static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct cmd_reflog_expire_cb cmd = { 0 }; timestamp_t now = time(NULL); @@ -394,7 +397,8 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) return status; } -static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) +static int cmd_reflog_delete(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i, status = 0; unsigned int flags = 0; @@ -424,7 +428,8 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) return status; } -static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) +static int cmd_reflog_exists(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -447,7 +452,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) * main "reflog" */ -int cmd_reflog(int argc, const char **argv, const char *prefix) +int cmd_reflog(int argc, + const char **argv, + const char *prefix, + struct repository *repository) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { @@ -464,7 +472,7 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); if (fn) - return fn(argc - 1, argv + 1, prefix); + return fn(argc - 1, argv + 1, prefix, repository); else - return cmd_log_reflog(argc, argv, prefix); + return cmd_log_reflog(argc, argv, prefix, repository); } diff --git a/builtin/refs.c b/builtin/refs.c index 46dcd150d4..a29f195834 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -1,13 +1,20 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" +#include "config.h" +#include "fsck.h" #include "parse-options.h" #include "refs.h" -#include "repository.h" #include "strbuf.h" +#include "worktree.h" #define REFS_MIGRATE_USAGE \ N_("git refs migrate --ref-format=<format> [--dry-run]") -static int cmd_refs_migrate(int argc, const char **argv, const char *prefix) +#define REFS_VERIFY_USAGE \ + N_("git refs verify [--strict] [--verbose]") + +static int cmd_refs_migrate(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { const char * const migrate_usage[] = { REFS_MIGRATE_USAGE, @@ -58,18 +65,56 @@ out: return err; } -int cmd_refs(int argc, const char **argv, const char *prefix) +static int cmd_refs_verify(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) +{ + struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; + struct worktree **worktrees; + const char * const verify_usage[] = { + REFS_VERIFY_USAGE, + NULL, + }; + struct option options[] = { + OPT_BOOL(0, "verbose", &fsck_refs_options.verbose, N_("be verbose")), + OPT_BOOL(0, "strict", &fsck_refs_options.strict, N_("enable strict checking")), + OPT_END(), + }; + int ret = 0; + + argc = parse_options(argc, argv, prefix, options, verify_usage, 0); + if (argc) + usage(_("'git refs verify' takes no arguments")); + + git_config(git_fsck_config, &fsck_refs_options); + prepare_repo_settings(the_repository); + + worktrees = get_worktrees(); + for (size_t i = 0; worktrees[i]; i++) + ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), + &fsck_refs_options, worktrees[i]); + + fsck_options_clear(&fsck_refs_options); + free_worktrees(worktrees); + return ret; +} + +int cmd_refs(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { const char * const refs_usage[] = { REFS_MIGRATE_USAGE, + REFS_VERIFY_USAGE, NULL, }; parse_opt_subcommand_fn *fn = NULL; struct option opts[] = { OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), + OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify), OPT_END(), }; argc = parse_options(argc, argv, prefix, opts, refs_usage, 0); - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index 282782eccd..33c8ae0fc7 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -195,7 +195,10 @@ static int command_loop(const char *child) } } -int cmd_remote_ext(int argc, const char **argv, const char *prefix) +int cmd_remote_ext(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { BUG_ON_NON_EMPTY_PREFIX(prefix); diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c index 9020fab9c5..ae896eda57 100644 --- a/builtin/remote-fd.c +++ b/builtin/remote-fd.c @@ -53,7 +53,10 @@ static void command_loop(int input_fd, int output_fd) } } -int cmd_remote_fd(int argc, const char **argv, const char *prefix) +int cmd_remote_fd(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int input_fd = -1; int output_fd = -1; diff --git a/builtin/remote.c b/builtin/remote.c index 9d54fddf8c..1ad3e70a6b 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -154,7 +155,8 @@ static int parse_mirror_opt(const struct option *opt, const char *arg, int not) return 0; } -static int add(int argc, const char **argv, const char *prefix) +static int add(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int fetch = 0, fetch_tags = TAGS_DEFAULT; unsigned mirror = MIRROR_NONE; @@ -164,6 +166,7 @@ static int add(int argc, const char **argv, const char *prefix) struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; const char *name, *url; int i; + int result = 0; struct option options[] = { OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")), @@ -230,8 +233,10 @@ static int add(int argc, const char **argv, const char *prefix) fetch_tags == TAGS_SET ? "--tags" : "--no-tags"); } - if (fetch && fetch_remote(name)) - return 1; + if (fetch && fetch_remote(name)) { + result = 1; + goto out; + } if (master) { strbuf_reset(&buf); @@ -241,14 +246,15 @@ static int add(int argc, const char **argv, const char *prefix) strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master); if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add")) - return error(_("Could not setup master '%s'"), master); + result = error(_("Could not setup master '%s'"), master); } +out: strbuf_release(&buf); strbuf_release(&buf2); string_list_clear(&track, 0); - return 0; + return result; } struct branch_info { @@ -372,7 +378,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat for (i = 0; i < states->remote->fetch.nr; i++) if (get_fetch_map(remote_refs, &states->remote->fetch.items[i], &tail, 1)) die(_("Could not get fetch map for refspec %s"), - states->remote->fetch.raw[i]); + states->remote->fetch.items[i].raw); for (ref = fetch_map; ref; ref = ref->next) { if (omit_name_by_refspec(ref->name, &states->remote->fetch)) @@ -544,6 +550,7 @@ struct branches_for_remote { }; static int add_branch_for_removal(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data) { @@ -589,7 +596,7 @@ struct rename_info { uint32_t symrefs_nr; }; -static int read_remote_branches(const char *refname, +static int read_remote_branches(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data) { @@ -627,12 +634,12 @@ static int migrate_file(struct remote *remote) git_config_set_multivar(buf.buf, remote->url.v[i], "^$", 0); strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.push", remote->name); - for (i = 0; i < remote->push.raw_nr; i++) - git_config_set_multivar(buf.buf, remote->push.raw[i], "^$", 0); + for (i = 0; i < remote->push.nr; i++) + git_config_set_multivar(buf.buf, remote->push.items[i].raw, "^$", 0); strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.fetch", remote->name); - for (i = 0; i < remote->fetch.raw_nr; i++) - git_config_set_multivar(buf.buf, remote->fetch.raw[i], "^$", 0); + for (i = 0; i < remote->fetch.nr; i++) + git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); if (remote->origin == REMOTE_REMOTES) unlink_or_warn(git_path("remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) @@ -700,7 +707,8 @@ static void handle_push_default(const char* old_name, const char* new_name) } -static int mv(int argc, const char **argv, const char *prefix) +static int mv(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int show_progress = isatty(2); struct option options[] = { @@ -714,6 +722,7 @@ static int mv(int argc, const char **argv, const char *prefix) struct rename_info rename; int i, refs_renamed_nr = 0, refspec_updated = 0; struct progress *progress = NULL; + int result = 0; argc = parse_options(argc, argv, prefix, options, builtin_remote_rename_usage, 0); @@ -746,20 +755,22 @@ static int mv(int argc, const char **argv, const char *prefix) strbuf_addf(&buf, "remote.%s", rename.old_name); strbuf_addf(&buf2, "remote.%s", rename.new_name); - if (git_config_rename_section(buf.buf, buf2.buf) < 1) - return error(_("Could not rename config section '%s' to '%s'"), - buf.buf, buf2.buf); + if (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1) { + result = error(_("Could not rename config section '%s' to '%s'"), + buf.buf, buf2.buf); + goto out; + } - if (oldremote->fetch.raw_nr) { + if (oldremote->fetch.nr) { strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.fetch", rename.new_name); git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE); strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name); - for (i = 0; i < oldremote->fetch.raw_nr; i++) { + for (i = 0; i < oldremote->fetch.nr; i++) { char *ptr; strbuf_reset(&buf2); - strbuf_addstr(&buf2, oldremote->fetch.raw[i]); + strbuf_addstr(&buf2, oldremote->fetch.items[i].raw); ptr = strstr(buf2.buf, old_remote_context.buf); if (ptr) { refspec_updated = 1; @@ -869,10 +880,11 @@ out: strbuf_release(&buf); strbuf_release(&buf2); strbuf_release(&buf3); - return 0; + return result; } -static int rm(int argc, const char **argv, const char *prefix) +static int rm(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -959,7 +971,7 @@ static int rm(int argc, const char **argv, const char *prefix) if (!result) { strbuf_addf(&buf, "remote.%s", remote->name); - if (git_config_rename_section(buf.buf, NULL) < 1) { + if (repo_config_rename_section(the_repository, buf.buf, NULL) < 1) { result = error(_("Could not remove config section '%s'"), buf.buf); goto out; } @@ -995,6 +1007,7 @@ static void free_remote_ref_states(struct ref_states *states) } static int append_ref_to_tracked_list(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags, void *cb_data) { @@ -1293,7 +1306,8 @@ static int show_all(void) return result; } -static int show(int argc, const char **argv, const char *prefix) +static int show(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int no_query = 0, result = 0, query_flag = 0; struct option options[] = { @@ -1389,7 +1403,8 @@ static int show(int argc, const char **argv, const char *prefix) return result; } -static int set_head(int argc, const char **argv, const char *prefix) +static int set_head(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i, opt_a = 0, opt_d = 0, result = 0; struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; @@ -1493,7 +1508,8 @@ static int prune_remote(const char *remote, int dry_run) return result; } -static int prune(int argc, const char **argv, const char *prefix) +static int prune(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int dry_run = 0, result = 0; struct option options[] = { @@ -1524,7 +1540,8 @@ static int get_remote_default(const char *key, const char *value UNUSED, return 0; } -static int update(int argc, const char **argv, const char *prefix) +static int update(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i, prune = -1; struct option options[] = { @@ -1606,7 +1623,8 @@ static int set_remote_branches(const char *remotename, const char **branches, return 0; } -static int set_branches(int argc, const char **argv, const char *prefix) +static int set_branches(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int add_mode = 0; struct option options[] = { @@ -1625,7 +1643,8 @@ static int set_branches(int argc, const char **argv, const char *prefix) return set_remote_branches(argv[0], argv + 1, add_mode); } -static int get_url(int argc, const char **argv, const char *prefix) +static int get_url(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i, push_mode = 0, all_mode = 0; const char *remotename = NULL; @@ -1664,7 +1683,8 @@ static int get_url(int argc, const char **argv, const char *prefix) return 0; } -static int set_url(int argc, const char **argv, const char *prefix) +static int set_url(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i, push_mode = 0, add_mode = 0, delete_mode = 0; int matches = 0, negative_matches = 0; @@ -1752,7 +1772,10 @@ out: return 0; } -int cmd_remote(int argc, const char **argv, const char *prefix) +int cmd_remote(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { @@ -1775,7 +1798,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix) PARSE_OPT_SUBCOMMAND_OPTIONAL); if (fn) { - return !!fn(argc, argv, prefix); + return !!fn(argc, argv, prefix, repo); } else { if (argc) { error(_("unknown subcommand: `%s'"), argv[0]); diff --git a/builtin/repack.c b/builtin/repack.c index f0317fa94a..9c21fc482d 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -85,17 +86,34 @@ static int repack_config(const char *var, const char *value, run_update_server_info = git_config_bool(var, value); return 0; } - if (!strcmp(var, "repack.cruftwindow")) + if (!strcmp(var, "repack.cruftwindow")) { + free(cruft_po_args->window); return git_config_string(&cruft_po_args->window, var, value); - if (!strcmp(var, "repack.cruftwindowmemory")) + } + if (!strcmp(var, "repack.cruftwindowmemory")) { + free(cruft_po_args->window_memory); return git_config_string(&cruft_po_args->window_memory, var, value); - if (!strcmp(var, "repack.cruftdepth")) + } + if (!strcmp(var, "repack.cruftdepth")) { + free(cruft_po_args->depth); return git_config_string(&cruft_po_args->depth, var, value); - if (!strcmp(var, "repack.cruftthreads")) + } + if (!strcmp(var, "repack.cruftthreads")) { + free(cruft_po_args->threads); return git_config_string(&cruft_po_args->threads, var, value); + } return git_default_config(var, value, ctx, cb); } +static void pack_objects_args_release(struct pack_objects_args *args) +{ + free(args->window); + free(args->window_memory); + free(args->depth); + free(args->threads); + list_objects_filter_release(&args->filter_options); +} + struct existing_packs { struct string_list kept_packs; struct string_list non_kept_packs; @@ -386,7 +404,7 @@ static void repack_promisor_objects(const struct pack_objects_args *args, * {type -> existing pack order} ordering when computing deltas instead * of a {type -> size} ordering, which may produce better deltas. */ - for_each_packed_object(write_oid, &cmd, + for_each_packed_object(the_repository, write_oid, &cmd, FOR_EACH_OBJECT_PROMISOR_ONLY); if (cmd.in == -1) { @@ -425,9 +443,11 @@ static void repack_promisor_objects(const struct pack_objects_args *args, free(promisor_name); } + fclose(out); if (finish_command(&cmd)) die(_("could not finish pack-objects to repack promisor objects")); + strbuf_release(&line); } struct pack_geometry { @@ -667,6 +687,7 @@ struct midx_snapshot_ref_data { }; static int midx_snapshot_ref_one(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *_data) { @@ -731,14 +752,23 @@ static void midx_included_packs(struct string_list *include, struct pack_geometry *geometry) { struct string_list_item *item; + struct strbuf buf = STRBUF_INIT; + + for_each_string_list_item(item, &existing->kept_packs) { + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); + } + + for_each_string_list_item(item, names) { + strbuf_reset(&buf); + strbuf_addf(&buf, "pack-%s.idx", item->string); + string_list_insert(include, buf.buf); + } - for_each_string_list_item(item, &existing->kept_packs) - string_list_insert(include, xstrfmt("%s.idx", item->string)); - for_each_string_list_item(item, names) - string_list_insert(include, xstrfmt("pack-%s.idx", item->string)); if (geometry->split_factor) { - struct strbuf buf = STRBUF_INIT; uint32_t i; + for (i = geometry->split; i < geometry->pack_nr; i++) { struct packed_git *p = geometry->pack[i]; @@ -753,17 +783,21 @@ static void midx_included_packs(struct string_list *include, if (!p->pack_local) continue; + strbuf_reset(&buf); strbuf_addstr(&buf, pack_basename(p)); strbuf_strip_suffix(&buf, ".pack"); strbuf_addstr(&buf, ".idx"); - string_list_insert(include, strbuf_detach(&buf, NULL)); + string_list_insert(include, buf.buf); } } else { for_each_string_list_item(item, &existing->non_kept_packs) { if (pack_is_marked_for_deletion(item)) continue; - string_list_insert(include, xstrfmt("%s.idx", item->string)); + + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); } } @@ -783,8 +817,13 @@ static void midx_included_packs(struct string_list *include, */ if (pack_is_marked_for_deletion(item)) continue; - string_list_insert(include, xstrfmt("%s.idx", item->string)); + + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); } + + strbuf_release(&buf); } static int write_midx_included_packs(struct string_list *include, @@ -1115,7 +1154,10 @@ static const char *find_pack_prefix(const char *packdir, const char *packtmp) return pack_prefix; } -int cmd_repack(int argc, const char **argv, const char *prefix) +int cmd_repack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct child_process cmd = CHILD_PROCESS_INIT; struct string_list_item *item; @@ -1131,12 +1173,16 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *unpack_unreachable = NULL; int keep_unreachable = 0; struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; - struct pack_objects_args po_args = {NULL}; - struct pack_objects_args cruft_po_args = {NULL}; + struct pack_objects_args po_args = { 0 }; + struct pack_objects_args cruft_po_args = { 0 }; int write_midx = 0; const char *cruft_expiration = NULL; const char *expire_to = NULL; const char *filter_to = NULL; + const char *opt_window = NULL; + const char *opt_window_memory = NULL; + const char *opt_depth = NULL; + const char *opt_threads = NULL; struct option builtin_repack_options[] = { OPT_BIT('a', NULL, &pack_everything, @@ -1170,13 +1216,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("with -A, do not loosen objects older than this")), OPT_BOOL('k', "keep-unreachable", &keep_unreachable, N_("with -a, repack unreachable objects")), - OPT_STRING(0, "window", &po_args.window, N_("n"), + OPT_STRING(0, "window", &opt_window, N_("n"), N_("size of the window used for delta compression")), - OPT_STRING(0, "window-memory", &po_args.window_memory, N_("bytes"), + OPT_STRING(0, "window-memory", &opt_window_memory, N_("bytes"), N_("same as the above, but limit memory size instead of entries count")), - OPT_STRING(0, "depth", &po_args.depth, N_("n"), + OPT_STRING(0, "depth", &opt_depth, N_("n"), N_("limits the maximum delta depth")), - OPT_STRING(0, "threads", &po_args.threads, N_("n"), + OPT_STRING(0, "threads", &opt_threads, N_("n"), N_("limits the maximum number of threads")), OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size, N_("maximum size of each packfile")), @@ -1203,6 +1249,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_repack_options, git_repack_usage, 0); + po_args.window = xstrdup_or_null(opt_window); + po_args.window_memory = xstrdup_or_null(opt_window_memory); + po_args.depth = xstrdup_or_null(opt_depth); + po_args.threads = xstrdup_or_null(opt_threads); + if (delete_redundant && repository_format_precious_objects) die(_("cannot delete packs in a precious-objects repo")); @@ -1217,10 +1268,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (!write_midx && (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository())) write_bitmaps = 0; - } else if (write_bitmaps && - git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0) && - git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP, 0)) { - write_bitmaps = 0; } if (pack_kept_objects < 0) pack_kept_objects = write_bitmaps > 0 && !write_midx; @@ -1243,7 +1290,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (write_midx && write_bitmaps) { struct strbuf path = STRBUF_INIT; - strbuf_addf(&path, "%s/%s_XXXXXX", get_object_directory(), + strbuf_addf(&path, "%s/%s_XXXXXX", repo_get_object_directory(the_repository), "bitmap-ref-tips"); refs_snapshot = xmks_tempfile(path.buf); @@ -1252,7 +1299,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) strbuf_release(&path); } - packdir = mkpathdup("%s/pack", get_object_directory()); + packdir = mkpathdup("%s/pack", repo_get_object_directory(the_repository)); packtmp_name = xstrfmt(".tmp-%d-pack", (int)getpid()); packtmp = mkpathdup("%s/%s", packdir, packtmp_name); @@ -1372,13 +1419,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *pack_prefix = find_pack_prefix(packdir, packtmp); if (!cruft_po_args.window) - cruft_po_args.window = po_args.window; + cruft_po_args.window = xstrdup_or_null(po_args.window); if (!cruft_po_args.window_memory) - cruft_po_args.window_memory = po_args.window_memory; + cruft_po_args.window_memory = xstrdup_or_null(po_args.window_memory); if (!cruft_po_args.depth) - cruft_po_args.depth = po_args.depth; + cruft_po_args.depth = xstrdup_or_null(po_args.depth); if (!cruft_po_args.threads) - cruft_po_args.threads = po_args.threads; + cruft_po_args.threads = xstrdup_or_null(po_args.threads); if (!cruft_po_args.max_pack_size) cruft_po_args.max_pack_size = po_args.max_pack_size; @@ -1479,7 +1526,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) mark_packs_for_deletion(&existing, &names); if (write_midx) { - struct string_list include = STRING_LIST_INIT_NODUP; + struct string_list include = STRING_LIST_INIT_DUP; midx_included_packs(&include, &existing, &names, &geometry); ret = write_midx_included_packs(&include, &geometry, &names, @@ -1520,16 +1567,19 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) { unsigned flags = 0; - if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP, 0)) - flags |= MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX; - write_midx_file(get_object_directory(), NULL, NULL, flags); + if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0)) + flags |= MIDX_WRITE_INCREMENTAL; + write_midx_file(the_repository, repo_get_object_directory(the_repository), + NULL, NULL, flags); } cleanup: + string_list_clear(&keep_pack_list, 0); string_list_clear(&names, 1); existing_packs_release(&existing); free_pack_geometry(&geometry); - list_objects_filter_release(&po_args.filter_options); + pack_objects_args_release(&po_args); + pack_objects_args_release(&cruft_po_args); return ret; } diff --git a/builtin/replace.c b/builtin/replace.c index 1ef833c07f..a4eaadff91 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -7,11 +7,10 @@ * and Carlos Rica <jasampler@gmail.com> that was itself based on * git-tag.sh and mktag.c by Linus Torvalds. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "editor.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" @@ -22,7 +21,6 @@ #include "object-name.h" #include "object-store-ll.h" #include "replace-object.h" -#include "repository.h" #include "tag.h" #include "wildmatch.h" @@ -49,6 +47,7 @@ struct show_data { }; static int show_reference(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -202,7 +201,7 @@ static int replace_object_oid(const char *object_ref, } transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction || ref_transaction_update(transaction, ref.buf, repl, &prev, NULL, NULL, 0, NULL, &err) || @@ -513,7 +512,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle) static int convert_graft_file(int force) { - const char *graft_file = get_graft_file(the_repository); + const char *graft_file = repo_get_graft_file(the_repository); FILE *fp = fopen_or_warn(graft_file, "r"); struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT; struct strvec args = STRVEC_INIT; @@ -544,7 +543,10 @@ static int convert_graft_file(int force) return -1; } -int cmd_replace(int argc, const char **argv, const char *prefix) +int cmd_replace(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force = 0; int raw = 0; diff --git a/builtin/replay.c b/builtin/replay.c index 27b40eda98..2d12a4e403 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -4,6 +4,7 @@ #include "git-compat-util.h" +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "hex.h" @@ -274,7 +275,10 @@ static struct commit *pick_regular_commit(struct commit *pickme, return create_commit(result->tree, pickme, replayed_base); } -int cmd_replay(int argc, const char **argv, const char *prefix) +int cmd_replay(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *advance_name_opt = NULL; char *advance_name = NULL; @@ -384,7 +388,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) goto cleanup; } - init_merge_options(&merge_opt, the_repository); + init_basic_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; last_commit = onto; diff --git a/builtin/rerere.c b/builtin/rerere.c index 81b65ffa39..f7143c3f5d 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -1,8 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" -#include "repository.h" + #include "string-list.h" #include "rerere.h" #include "xdiff/xdiff.h" @@ -48,7 +49,10 @@ static int diff_two(const char *file1, const char *label1, return ret; } -int cmd_rerere(int argc, const char **argv, const char *prefix) +int cmd_rerere(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct string_list merge_rr = STRING_LIST_INIT_DUP; int i, autoupdate = -1, flags = 0; diff --git a/builtin/reset.c b/builtin/reset.c index 5f941fb3a2..7154f88826 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -7,7 +7,7 @@ * * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -26,6 +26,7 @@ #include "object-name.h" #include "parse-options.h" #include "path.h" +#include "repository.h" #include "unpack-trees.h" #include "cache-tree.h" #include "setup.h" @@ -330,7 +331,10 @@ static int git_reset_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_reset(int argc, const char **argv, const char *prefix) +int cmd_reset(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int reset_type = NONE, update_ref_status = 0, quiet = 0; int no_refresh = 0; @@ -441,7 +445,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) else trace2_cmd_mode(reset_type_names[reset_type]); - if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree())) + if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository))) setup_work_tree(); if (reset_type == MIXED && is_bare_repository()) @@ -474,7 +478,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) goto cleanup; } the_repository->index->updated_skipworktree = 1; - if (!no_refresh && get_git_work_tree()) { + if (!no_refresh && repo_get_work_tree(the_repository)) { uint64_t t_begin, t_delta_in_ms; t_begin = getnanotime(); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 97d077a994..8fe83893fa 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -120,7 +121,7 @@ static inline void finish_object__ma(struct object *obj) return; case MA_ALLOW_PROMISOR: - if (is_promisor_object(&obj->oid)) + if (is_promisor_object(the_repository, &obj->oid)) return; die("unexpected missing %s object '%s'", type_name(obj->type), oid_to_hex(&obj->oid)); @@ -484,6 +485,13 @@ static int try_bitmap_traversal(struct rev_info *revs, if (revs->max_count >= 0) return -1; + /* + * We can't know which commits were left/right in a single traversal, + * and we don't yet know how to traverse them separately. + */ + if (revs->left_right) + return -1; + bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects); if (!bitmap_git) return -1; @@ -513,7 +521,10 @@ static int try_bitmap_disk_usage(struct rev_info *revs, return 0; } -int cmd_rev_list(int argc, const char **argv, const char *prefix) +int cmd_rev_list(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct rev_list_info info; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 5845d3f59b..8401b4d7ab 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -3,8 +3,9 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "config.h" #include "commit.h" @@ -19,6 +20,8 @@ #include "path.h" #include "diff.h" #include "read-cache-ll.h" +#include "repo-settings.h" +#include "repository.h" #include "revision.h" #include "setup.h" #include "split-index.h" @@ -211,7 +214,7 @@ static int show_default(void) return 0; } -static int show_reference(const char *refname, const struct object_id *oid, +static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { if (ref_excluded(&ref_excludes, refname)) @@ -220,7 +223,7 @@ static int show_reference(const char *refname, const struct object_id *oid, return 0; } -static int anti_reference(const char *refname, const struct object_id *oid, +static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { show_rev(REVERSED, oid, refname); @@ -688,7 +691,10 @@ static void print_path(const char *path, const char *prefix, enum format_type fo free(cwd); } -int cmd_rev_parse(int argc, const char **argv, const char *prefix) +int cmd_rev_parse(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; const struct git_hash_algo *output_algo = NULL; @@ -898,7 +904,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } if (opt_with_value(arg, "--abbrev-ref", &arg)) { abbrev_ref = 1; - abbrev_ref_strict = warn_ambiguous_refs; + abbrev_ref_strict = + repo_settings_get_warn_ambiguous_refs(the_repository); if (arg) { if (!strcmp(arg, "strict")) abbrev_ref_strict = 1; @@ -966,7 +973,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--show-toplevel")) { - const char *work_tree = get_git_work_tree(); + const char *work_tree = repo_get_work_tree(the_repository); if (work_tree) print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED); else @@ -991,7 +998,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) const char *pfx = prefix; if (!is_inside_work_tree()) { const char *work_tree = - get_git_work_tree(); + repo_get_work_tree(the_repository); if (work_tree) printf("%s\n", work_tree); continue; @@ -1042,7 +1049,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--git-common-dir")) { - print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED); + print_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED); continue; } if (!strcmp(arg, "--is-inside-git-dir")) { diff --git a/builtin/revert.c b/builtin/revert.c index 7bf2b4e11d..b7917dddd3 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "builtin.h" #include "parse-options.h" #include "diff.h" #include "gettext.h" -#include "repository.h" #include "revision.h" #include "rerere.h" #include "sequencer.h" @@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char *me = action_name(opts); const char *cleanup_arg = NULL; + const char sentinel_value; + const char *strategy = &sentinel_value; + const char *gpg_sign = &sentinel_value; enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; int cmd = 0; struct option base_options[] = { @@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, OPT_CALLBACK('m', "mainline", opts, N_("parent-number"), N_("select mainline parent"), option_parse_m), OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto), - OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")), + OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"), N_("option for merge strategy")), - { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), + { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_END() }; @@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, usage_with_options(usage_str, options); /* These option values will be free()d */ - opts->gpg_sign = xstrdup_or_null(opts->gpg_sign); - opts->strategy = xstrdup_or_null(opts->strategy); + if (gpg_sign != &sentinel_value) { + free(opts->gpg_sign); + opts->gpg_sign = xstrdup_or_null(gpg_sign); + } + if (strategy != &sentinel_value) { + free(opts->strategy); + opts->strategy = xstrdup_or_null(strategy); + } if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); free(options); @@ -261,7 +270,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, return sequencer_pick_revisions(the_repository, opts); } -int cmd_revert(int argc, const char **argv, const char *prefix) +int cmd_revert(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct replay_opts opts = REPLAY_OPTS_INIT; int res; @@ -275,7 +287,10 @@ int cmd_revert(int argc, const char **argv, const char *prefix) return res; } -int cmd_cherry_pick(int argc, const char **argv, const char *prefix) +int cmd_cherry_pick(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct replay_opts opts = REPLAY_OPTS_INIT; int res; diff --git a/builtin/rm.c b/builtin/rm.c index 0e79cbab62..eaff027258 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds 2006 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -15,7 +15,7 @@ #include "object-name.h" #include "parse-options.h" #include "read-cache.h" -#include "repository.h" + #include "string-list.h" #include "setup.h" #include "sparse-index.h" @@ -261,7 +261,10 @@ static struct option builtin_rm_options[] = { OPT_END(), }; -int cmd_rm(int argc, const char **argv, const char *prefix) +int cmd_rm(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct lock_file lock_file = LOCK_INIT; int i, ret = 0; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 17cae6bbbd..59b626aae8 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -147,7 +148,10 @@ static int send_pack_config(const char *k, const char *v, return git_default_config(k, v, ctx, cb); } -int cmd_send_pack(int argc, const char **argv, const char *prefix) +int cmd_send_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -336,7 +340,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) /* stable plumbing output; do not modify or localize */ fprintf(stderr, "Everything up-to-date\n"); + string_list_clear(&push_options, 0); free_refs(remote_refs); free_refs(local_refs); + refspec_clear(&rs); + oid_array_clear(&shallow); + clear_cas_option(&cas); return ret; } diff --git a/builtin/shortlog.c b/builtin/shortlog.c index b529608c92..c86b75d981 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -5,7 +6,6 @@ #include "environment.h" #include "gettext.h" #include "string-list.h" -#include "repository.h" #include "revision.h" #include "utf8.h" #include "mailmap.h" @@ -378,7 +378,10 @@ void shortlog_finish_setup(struct shortlog *log) string_list_sort(&log->trailers); } -int cmd_shortlog(int argc, const char **argv, const char *prefix) +int cmd_shortlog(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct shortlog log = { STRING_LIST_INIT_NODUP }; struct rev_info rev; @@ -404,6 +407,18 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) struct parse_opt_ctx_t ctx; + /* + * NEEDSWORK: Later on we'll call parse_revision_opt which relies on + * the hash algorithm being set but since we are operating outside of a + * Git repository we cannot determine one. This is only needed because + * parse_revision_opt expects hexsz for --abbrev which is irrelevant + * for shortlog outside of a git repository. For now explicitly set + * SHA1, but ideally the parsing machinery would be split between + * git/nongit so that we do not have to do this. + */ + if (nongit && !the_hash_algo) + repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + git_config(git_default_config, NULL); shortlog_init(&log); repo_init_revisions(the_repository, &rev, prefix); diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 7d797a880c..cd6bdf63bc 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -10,7 +11,7 @@ #include "strvec.h" #include "object-name.h" #include "parse-options.h" -#include "repository.h" + #include "dir.h" #include "commit-slab.h" #include "date.h" @@ -410,7 +411,7 @@ static int append_ref(const char *refname, const struct object_id *oid, return 0; } -static int append_head_ref(const char *refname, const struct object_id *oid, +static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id tmp; @@ -425,7 +426,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid, return append_ref(refname + ofs, oid, 0); } -static int append_remote_ref(const char *refname, const struct object_id *oid, +static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id tmp; @@ -451,7 +452,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid, static const char *match_ref_pattern = NULL; static int match_ref_slash = 0; -static int append_matching_ref(const char *refname, const struct object_id *oid, +static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { /* we want to allow pattern hold/<asterisk> to show all @@ -468,7 +469,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid, if (wildmatch(match_ref_pattern, tail, 0)) return 0; if (starts_with(refname, "refs/heads/")) - return append_head_ref(refname, oid, flag, cb_data); + return append_head_ref(refname, NULL, oid, flag, cb_data); if (starts_with(refname, "refs/tags/")) return append_tag_ref(refname, oid, flag, cb_data); return append_ref(refname, oid, 0); @@ -632,7 +633,10 @@ static int parse_reflog_param(const struct option *opt, const char *arg, return 0; } -int cmd_show_branch(int ac, const char **av, const char *prefix) +int cmd_show_branch(int ac, + const char **av, + const char *prefix, + struct repository *repo UNUSED) { struct commit *rev[MAX_REVS], *commit; char *reflog_msg[MAX_REVS] = {0}; diff --git a/builtin/show-index.c b/builtin/show-index.c index 540dc3dad1..f164c01bbe 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -1,17 +1,20 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hash.h" #include "hex.h" #include "pack.h" #include "parse-options.h" -#include "repository.h" static const char *const show_index_usage[] = { "git show-index [--object-format=<hash-algorithm>]", NULL }; -int cmd_show_index(int argc, const char **argv, const char *prefix) +int cmd_show_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; unsigned nr; diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 839a5c29f3..285cd3e433 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -63,7 +64,7 @@ struct show_ref_data { int show_head; }; -static int show_ref(const char *refname, const struct object_id *oid, +static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cbdata) { struct show_ref_data *data = cbdata; @@ -97,6 +98,7 @@ match: } static int add_existing(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cbdata) { @@ -286,15 +288,18 @@ static int exclude_existing_callback(const struct option *opt, const char *arg, return 0; } -int cmd_show_ref(int argc, const char **argv, const char *prefix) +int cmd_show_ref(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct exclude_existing_options exclude_existing_opts = {0}; struct patterns_options patterns_opts = {0}; struct show_one_options show_one_opts = {0}; int verify = 0, exists = 0; const struct option show_ref_options[] = { - OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with branches)")), - OPT_BOOL(0, "branches", &patterns_opts.branches_only, N_("only show branches (can be combined with tags)")), + OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with --branches)")), + OPT_BOOL(0, "branches", &patterns_opts.branches_only, N_("only show branches (can be combined with --tags)")), OPT_HIDDEN_BOOL(0, "heads", &patterns_opts.branches_only, N_("deprecated synonym for --branches")), OPT_BOOL(0, "exists", &exists, N_("check for reference existence without resolving")), diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 2604ab04df..34af5b2590 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -7,7 +8,6 @@ #include "object-name.h" #include "parse-options.h" #include "pathspec.h" -#include "repository.h" #include "strbuf.h" #include "string-list.h" #include "lockfile.h" @@ -48,7 +48,8 @@ static char const * const builtin_sparse_checkout_list_usage[] = { NULL }; -static int sparse_checkout_list(int argc, const char **argv, const char *prefix) +static int sparse_checkout_list(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_sparse_checkout_list_options[] = { OPT_END(), @@ -327,7 +328,6 @@ static int write_patterns_and_update(struct pattern_list *pl) { char *sparse_filename; FILE *fp; - int fd; struct lock_file lk = LOCK_INIT; int result; @@ -336,31 +336,31 @@ static int write_patterns_and_update(struct pattern_list *pl) if (safe_create_leading_directories(sparse_filename)) die(_("failed to create directory for sparse-checkout file")); - fd = hold_lock_file_for_update(&lk, sparse_filename, - LOCK_DIE_ON_ERROR); - free(sparse_filename); + hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR); result = update_working_directory(pl); if (result) { rollback_lock_file(&lk); - clear_pattern_list(pl); update_working_directory(NULL); - return result; + goto out; } - fp = xfdopen(fd, "w"); + fp = fdopen_lock_file(&lk, "w"); + if (!fp) + die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk)); if (core_sparse_checkout_cone) write_cone_to_file(fp, pl); else write_patterns_to_file(fp, pl); - fflush(fp); - commit_lock_file(&lk); + if (commit_lock_file(&lk)) + die_errno(_("unable to write %s"), sparse_filename); +out: clear_pattern_list(pl); - - return 0; + free(sparse_filename); + return result; } enum sparse_checkout_mode { @@ -444,7 +444,8 @@ static struct sparse_checkout_init_opts { int sparse_index; } init_opts; -static int sparse_checkout_init(int argc, const char **argv, const char *prefix) +static int sparse_checkout_init(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct pattern_list pl; char *sparse_filename; @@ -670,7 +671,7 @@ static void add_patterns_literal(int argc, const char **argv, add_patterns_from_input(pl, argc, argv, use_stdin ? stdin : NULL); } -static int modify_pattern_list(int argc, const char **argv, int use_stdin, +static int modify_pattern_list(struct strvec *args, int use_stdin, enum modify_type m) { int result; @@ -680,13 +681,13 @@ static int modify_pattern_list(int argc, const char **argv, int use_stdin, switch (m) { case ADD: if (core_sparse_checkout_cone) - add_patterns_cone_mode(argc, argv, pl, use_stdin); + add_patterns_cone_mode(args->nr, args->v, pl, use_stdin); else - add_patterns_literal(argc, argv, pl, use_stdin); + add_patterns_literal(args->nr, args->v, pl, use_stdin); break; case REPLACE: - add_patterns_from_input(pl, argc, argv, + add_patterns_from_input(pl, args->nr, args->v, use_stdin ? stdin : NULL); break; } @@ -707,12 +708,12 @@ static int modify_pattern_list(int argc, const char **argv, int use_stdin, return result; } -static void sanitize_paths(int argc, const char **argv, +static void sanitize_paths(struct strvec *args, const char *prefix, int skip_checks) { int i; - if (!argc) + if (!args->nr) return; if (prefix && *prefix && core_sparse_checkout_cone) { @@ -722,8 +723,11 @@ static void sanitize_paths(int argc, const char **argv, */ int prefix_len = strlen(prefix); - for (i = 0; i < argc; i++) - argv[i] = prefix_path(prefix, prefix_len, argv[i]); + for (i = 0; i < args->nr; i++) { + char *prefixed_path = prefix_path(prefix, prefix_len, args->v[i]); + strvec_replace(args, i, prefixed_path); + free(prefixed_path); + } } if (skip_checks) @@ -733,20 +737,20 @@ static void sanitize_paths(int argc, const char **argv, die(_("please run from the toplevel directory in non-cone mode")); if (core_sparse_checkout_cone) { - for (i = 0; i < argc; i++) { - if (argv[i][0] == '/') + for (i = 0; i < args->nr; i++) { + if (args->v[i][0] == '/') die(_("specify directories rather than patterns (no leading slash)")); - if (argv[i][0] == '!') + if (args->v[i][0] == '!') die(_("specify directories rather than patterns. If your directory starts with a '!', pass --skip-checks")); - if (strpbrk(argv[i], "*?[]")) + if (strpbrk(args->v[i], "*?[]")) die(_("specify directories rather than patterns. If your directory really has any of '*?[]\\' in it, pass --skip-checks")); } } - for (i = 0; i < argc; i++) { + for (i = 0; i < args->nr; i++) { struct cache_entry *ce; struct index_state *index = the_repository->index; - int pos = index_name_pos(index, argv[i], strlen(argv[i])); + int pos = index_name_pos(index, args->v[i], strlen(args->v[i])); if (pos < 0) continue; @@ -755,9 +759,9 @@ static void sanitize_paths(int argc, const char **argv, continue; if (core_sparse_checkout_cone) - die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), argv[i]); + die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), args->v[i]); else - warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), argv[i]); + warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), args->v[i]); } } @@ -771,7 +775,8 @@ static struct sparse_checkout_add_opts { int use_stdin; } add_opts; -static int sparse_checkout_add(int argc, const char **argv, const char *prefix) +static int sparse_checkout_add(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_sparse_checkout_add_options[] = { OPT_BOOL_F(0, "skip-checks", &add_opts.skip_checks, @@ -781,6 +786,8 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix) N_("read patterns from standard in")), OPT_END(), }; + struct strvec patterns = STRVEC_INIT; + int ret; setup_work_tree(); if (!core_apply_sparse_checkout) @@ -792,9 +799,14 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix) builtin_sparse_checkout_add_options, builtin_sparse_checkout_add_usage, 0); - sanitize_paths(argc, argv, prefix, add_opts.skip_checks); + for (int i = 0; i < argc; i++) + strvec_push(&patterns, argv[i]); + sanitize_paths(&patterns, prefix, add_opts.skip_checks); - return modify_pattern_list(argc, argv, add_opts.use_stdin, ADD); + ret = modify_pattern_list(&patterns, add_opts.use_stdin, ADD); + + strvec_clear(&patterns); + return ret; } static char const * const builtin_sparse_checkout_set_usage[] = { @@ -809,7 +821,8 @@ static struct sparse_checkout_set_opts { int use_stdin; } set_opts; -static int sparse_checkout_set(int argc, const char **argv, const char *prefix) +static int sparse_checkout_set(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int default_patterns_nr = 2; const char *default_patterns[] = {"/*", "!/*/", NULL}; @@ -827,6 +840,8 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix) PARSE_OPT_NONEG), OPT_END(), }; + struct strvec patterns = STRVEC_INIT; + int ret; setup_work_tree(); repo_read_index(the_repository); @@ -847,13 +862,18 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix) * top-level directory (much as 'init' would do). */ if (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) { - argv = default_patterns; - argc = default_patterns_nr; + for (int i = 0; i < default_patterns_nr; i++) + strvec_push(&patterns, default_patterns[i]); } else { - sanitize_paths(argc, argv, prefix, set_opts.skip_checks); + for (int i = 0; i < argc; i++) + strvec_push(&patterns, argv[i]); + sanitize_paths(&patterns, prefix, set_opts.skip_checks); } - return modify_pattern_list(argc, argv, set_opts.use_stdin, REPLACE); + ret = modify_pattern_list(&patterns, set_opts.use_stdin, REPLACE); + + strvec_clear(&patterns); + return ret; } static char const * const builtin_sparse_checkout_reapply_usage[] = { @@ -867,7 +887,8 @@ static struct sparse_checkout_reapply_opts { } reapply_opts; static int sparse_checkout_reapply(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_sparse_checkout_reapply_options[] = { OPT_BOOL(0, "cone", &reapply_opts.cone_mode, @@ -902,7 +923,8 @@ static char const * const builtin_sparse_checkout_disable_usage[] = { }; static int sparse_checkout_disable(int argc, const char **argv, - const char *prefix) + const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_sparse_checkout_disable_options[] = { OPT_END(), @@ -925,6 +947,11 @@ static int sparse_checkout_disable(int argc, const char **argv, builtin_sparse_checkout_disable_options, builtin_sparse_checkout_disable_usage, 0); + /* + * Disable the advice message for expanding a sparse index, as we + * are expecting to do that when disabling sparse-checkout. + */ + give_advice_on_expansion = 0; repo_read_index(the_repository); memset(&pl, 0, sizeof(pl)); @@ -985,7 +1012,8 @@ static int check_rules(struct pattern_list *pl, int null_terminated) { return 0; } -static int sparse_checkout_check_rules(int argc, const char **argv, const char *prefix) +static int sparse_checkout_check_rules(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_sparse_checkout_check_rules_options[] = { OPT_BOOL('z', NULL, &check_rules_opts.null_termination, @@ -1030,7 +1058,10 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char * return ret; } -int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) +int cmd_sparse_checkout(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_sparse_checkout_options[] = { @@ -1053,5 +1084,5 @@ int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/stash.c b/builtin/stash.c index 7f2f989b69..c212b1c0b2 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -19,6 +20,7 @@ #include "entry.h" #include "preload-index.h" #include "read-cache.h" +#include "repository.h" #include "rerere.h" #include "revision.h" #include "setup.h" @@ -247,7 +249,8 @@ static int do_clear_stash(void) ref_stash, &obj, 0); } -static int clear_stash(int argc, const char **argv, const char *prefix) +static int clear_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -484,7 +487,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree) " to make room.\n"), ce->name, new_path.buf); if (rename(ce->name, new_path.buf)) - die("Failed to move %s to %s\n", + die("Failed to move %s to %s", ce->name, new_path.buf); strbuf_release(&new_path); } @@ -539,8 +542,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, NULL, NULL, NULL)) return error(_("could not write index")); - if (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0, - NULL)) + if (write_index_as_tree(&c_tree, the_repository->index, + repo_get_index_file(the_repository), 0, NULL)) return error(_("cannot apply a stash in the middle of a merge")); if (index) { @@ -565,7 +568,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, discard_index(the_repository->index); repo_read_index(the_repository); if (write_index_as_tree(&index_tree, the_repository->index, - get_index_file(), 0, NULL)) + repo_get_index_file(the_repository), 0, NULL)) return error(_("could not save index tree")); reset_head(); @@ -574,7 +577,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, } } - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.branch1 = "Updated upstream"; o.branch2 = "Stashed changes"; @@ -640,9 +643,9 @@ restore_untracked: cp.git_cmd = 1; cp.dir = prefix; strvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT"=%s", - absolute_path(get_git_work_tree())); + absolute_path(repo_get_work_tree(the_repository))); strvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT"=%s", - absolute_path(get_git_dir())); + absolute_path(repo_get_git_dir(the_repository))); strvec_push(&cp.args, "status"); run_command(&cp); } @@ -650,7 +653,8 @@ restore_untracked: return ret; } -static int apply_stash(int argc, const char **argv, const char *prefix) +static int apply_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int ret = -1; int quiet = 0; @@ -724,7 +728,8 @@ static int get_stash_info_assert(struct stash_info *info, int argc, return 0; } -static int drop_stash(int argc, const char **argv, const char *prefix) +static int drop_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int ret = -1; int quiet = 0; @@ -746,7 +751,8 @@ cleanup: return ret; } -static int pop_stash(int argc, const char **argv, const char *prefix) +static int pop_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int ret = -1; int index = 0; @@ -776,7 +782,8 @@ cleanup: return ret; } -static int branch_stash(int argc, const char **argv, const char *prefix) +static int branch_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int ret = -1; const char *branch = NULL; @@ -814,7 +821,8 @@ cleanup: return ret; } -static int list_stash(int argc, const char **argv, const char *prefix) +static int list_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct child_process cp = CHILD_PROCESS_INIT; struct option options[] = { @@ -887,7 +895,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op do_diff_cache(&info->b_commit, diff_opt); } -static int show_stash(int argc, const char **argv, const char *prefix) +static int show_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i; int ret = -1; @@ -974,7 +983,7 @@ static int show_stash(int argc, const char **argv, const char *prefix) } log_tree_diff_flush(&rev); - ret = diff_result_code(&rev.diffopt); + ret = diff_result_code(&rev); cleanup: strvec_clear(&revision_args); @@ -1015,7 +1024,8 @@ static int do_store_stash(const struct object_id *w_commit, const char *stash_ms return 0; } -static int store_stash(int argc, const char **argv, const char *prefix) +static int store_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int quiet = 0; const char *stash_msg = NULL; @@ -1126,13 +1136,13 @@ static int check_changes_tracked_files(const struct pathspec *ps) diff_setup_done(&rev.diffopt); run_diff_index(&rev, DIFF_INDEX_CACHED); - if (diff_result_code(&rev.diffopt)) { + if (diff_result_code(&rev)) { ret = 1; goto done; } run_diff_files(&rev, 0); - if (diff_result_code(&rev.diffopt)) { + if (diff_result_code(&rev)) { ret = 1; goto done; } @@ -1405,8 +1415,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf); commit_list_insert(head_commit, &parents); - if (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0, - NULL) || + if (write_index_as_tree(&info->i_tree, the_repository->index, + repo_get_index_file(the_repository), 0, NULL) || commit_tree(commit_tree_label.buf, commit_tree_label.len, &info->i_tree, parents, &info->i_commit, NULL, NULL)) { if (!quiet) @@ -1489,7 +1499,8 @@ done: return ret; } -static int create_stash(int argc, const char **argv, const char *prefix UNUSED) +static int create_stash(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { int ret; struct strbuf stash_msg_buf = STRBUF_INIT; @@ -1671,7 +1682,28 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q } } - if (keep_index == 1 && !is_null_oid(&info.i_tree)) { + /* + * When keeping staged entries, we need to reset the working + * directory to match the state of our index. This can be + * skipped when the index is the empty tree, because there is + * nothing to reset in that case: + * + * - When the index has any file, regardless of whether + * staged or not, the tree cannot be empty by definition + * and thus we enter the condition. + * + * - When the index has no files, the only thing we need to + * care about is untracked files when `--include-untracked` + * is given. But as we already execute git-clean(1) further + * up to delete such untracked files we don't have to do + * anything here, either. + * + * We thus skip calling git-checkout(1) in this case, also + * because running it on an empty tree will cause it to fail + * due to the pathspec not matching anything. + */ + if (keep_index == 1 && !is_null_oid(&info.i_tree) && + !is_empty_tree_oid(&info.i_tree, the_repository->hash_algo)) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; @@ -1736,7 +1768,7 @@ static int push_stash(int argc, const char **argv, const char *prefix, int quiet = 0; int pathspec_file_nul = 0; const char *stash_msg = NULL; - const char *pathspec_from_file = NULL; + char *pathspec_from_file = NULL; struct pathspec ps; struct option options[] = { OPT_BOOL('k', "keep-index", &keep_index, @@ -1798,16 +1830,20 @@ static int push_stash(int argc, const char **argv, const char *prefix, ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, include_untracked, only_staged); + clear_pathspec(&ps); + free(pathspec_from_file); return ret; } -static int push_stash_unassumed(int argc, const char **argv, const char *prefix) +static int push_stash_unassumed(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { return push_stash(argc, argv, prefix, 0); } -static int save_stash(int argc, const char **argv, const char *prefix) +static int save_stash(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int keep_index = -1; int only_staged = 0; @@ -1850,7 +1886,10 @@ static int save_stash(int argc, const char **argv, const char *prefix) return ret; } -int cmd_stash(int argc, const char **argv, const char *prefix) +int cmd_stash(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { pid_t pid = getpid(); const char *index_file; @@ -1883,14 +1922,14 @@ int cmd_stash(int argc, const char **argv, const char *prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - index_file = get_index_file(); + index_file = repo_get_index_file(the_repository); strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file, (uintmax_t)pid); if (fn) - return !!fn(argc, argv, prefix); + return !!fn(argc, argv, prefix, repo); else if (!argc) - return !!push_stash_unassumed(0, NULL, prefix); + return !!push_stash_unassumed(0, NULL, prefix, repo); /* Assume 'stash push' */ strvec_push(&args, "push"); diff --git a/builtin/stripspace.c b/builtin/stripspace.c index e5626e5126..e147f3ff92 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -29,7 +30,10 @@ enum stripspace_mode { COMMENT_LINES }; -int cmd_stripspace(int argc, const char **argv, const char *prefix) +int cmd_stripspace(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buf = STRBUF_INIT; enum stripspace_mode mode = STRIP_DEFAULT; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 673810d2c0..19e5878381 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1,9 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" + #include "config.h" #include "parse-options.h" #include "quote.h" @@ -363,9 +364,13 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, if (!info->quiet) printf(_("Entering '%s'\n"), displaypath); - if (info->argv[0] && run_command(&cp)) - die(_("run_command returned non-zero status for %s\n."), - displaypath); + if (info->argv[0]) { + if (run_command(&cp)) + die(_("run_command returned non-zero status for %s\n."), + displaypath); + } else { + child_process_clear(&cp); + } if (info->recursive) { struct child_process cpr = CHILD_PROCESS_INIT; @@ -394,7 +399,8 @@ cleanup: free(displaypath); } -static int module_foreach(int argc, const char **argv, const char *prefix) +static int module_foreach(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct foreach_cb info = FOREACH_CB_INIT; struct pathspec pathspec = { 0 }; @@ -539,7 +545,8 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data info->flags); } -static int module_init(int argc, const char **argv, const char *prefix) +static int module_init(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct init_cb info = INIT_CB_INIT; struct pathspec pathspec = { 0 }; @@ -608,6 +615,7 @@ static void print_status(unsigned int flags, char state, const char *path, } static int handle_submodule_head_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) @@ -671,7 +679,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt); run_diff_files(&rev, 0); - if (!diff_result_code(&rev.diffopt)) { + if (!diff_result_code(&rev)) { print_status(flags, ' ', path, ce_oid, displaypath); } else if (!(flags & OPT_CACHED)) { @@ -694,6 +702,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_RECURSIVE) { struct child_process cpr = CHILD_PROCESS_INIT; + int res; cpr.git_cmd = 1; cpr.dir = path; @@ -709,7 +718,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_QUIET) strvec_push(&cpr.args, "--quiet"); - if (run_command(&cpr)) + res = run_command(&cpr); + if (res == SIGPIPE + 128) + raise(SIGPIPE); + else if (res) die(_("failed to recurse into submodule '%s'"), path); } @@ -728,7 +740,8 @@ static void status_submodule_cb(const struct cache_entry *list_item, info->prefix, info->super_prefix, info->flags); } -static int module_status(int argc, const char **argv, const char *prefix) +static int module_status(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct status_cb info = STATUS_CB_INIT; struct pathspec pathspec = { 0 }; @@ -916,7 +929,7 @@ static void generate_submodule_summary(struct summary_cb *info, } else { /* for a submodule removal (mode:0000000), don't warn */ if (p->mod_dst) - warning(_("unexpected mode %o\n"), p->mod_dst); + warning(_("unexpected mode %o"), p->mod_dst); } } @@ -1153,7 +1166,8 @@ cleanup: return ret; } -static int module_summary(int argc, const char **argv, const char *prefix) +static int module_summary(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct summary_cb info = SUMMARY_CB_INIT; int cached = 0; @@ -1329,7 +1343,8 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data info->flags); } -static int module_sync(int argc, const char **argv, const char *prefix) +static int module_sync(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct sync_cb info = SYNC_CB_INIT; struct pathspec pathspec = { 0 }; @@ -1455,7 +1470,7 @@ static void deinit_submodule(const char *path, const char *prefix, * remove the whole section so we have a clean state when * the user later decides to init this submodule again */ - git_config_rename_section_in_file(NULL, sub_key, NULL); + repo_config_rename_section_in_file(the_repository, NULL, sub_key, NULL); if (!(flags & OPT_QUIET)) printf(_("Submodule '%s' (%s) unregistered for path '%s'\n"), sub->name, sub->url, displaypath); @@ -1475,7 +1490,8 @@ static void deinit_submodule_cb(const struct cache_entry *list_item, deinit_submodule(list_item->name, info->prefix, info->flags); } -static int module_deinit(int argc, const char **argv, const char *prefix) +static int module_deinit(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct deinit_cb info = DEINIT_CB_INIT; struct pathspec pathspec = { 0 }; @@ -1532,6 +1548,7 @@ struct module_clone_data { const char *url; int depth; struct list_objects_filter_options *filter_options; + enum ref_storage_format ref_storage_format; unsigned int quiet: 1; unsigned int progress: 1; unsigned int dissociate: 1; @@ -1540,6 +1557,7 @@ struct module_clone_data { }; #define MODULE_CLONE_DATA_INIT { \ .single_branch = -1, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ } struct submodule_alternate_setup { @@ -1614,6 +1632,8 @@ static int add_possible_reference_from_superproject( ; /* nothing */ } } + + strbuf_release(&err); strbuf_release(&sb); } @@ -1706,7 +1726,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, exit(128); if (!is_absolute_path(clone_data->path)) - clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(), + clone_data_path = to_free = xstrfmt("%s/%s", repo_get_work_tree(the_repository), clone_data->path); if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0) @@ -1738,6 +1758,9 @@ static int clone_submodule(const struct module_clone_data *clone_data, strvec_pushl(&cp.args, "--reference", item->string, NULL); } + if (clone_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&cp.args, "--ref-format=%s", + ref_storage_format_to_name(clone_data->ref_storage_format)); if (clone_data->dissociate) strvec_push(&cp.args, "--dissociate"); if (sm_gitdir && *sm_gitdir) @@ -1825,13 +1848,15 @@ static int clone_submodule(const struct module_clone_data *clone_data, return 0; } -static int module_clone(int argc, const char **argv, const char *prefix) +static int module_clone(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int dissociate = 0, quiet = 0, progress = 0, require_init = 0; struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT; struct string_list reference = STRING_LIST_INIT_NODUP; struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; + const char *ref_storage_format = NULL; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &clone_data.prefix, @@ -1849,6 +1874,8 @@ static int module_clone(int argc, const char **argv, const char *prefix) OPT_STRING_LIST(0, "reference", &reference, N_("repo"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &dissociate, N_("use --reference only while cloning")), OPT_INTEGER(0, "depth", &clone_data.depth, @@ -1874,6 +1901,11 @@ static int module_clone(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, module_clone_options, git_submodule_helper_usage, 0); + if (ref_storage_format) { + clone_data.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (clone_data.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } clone_data.dissociate = !!dissociate; clone_data.quiet = !!quiet; clone_data.progress = !!progress; @@ -1973,6 +2005,7 @@ struct update_data { struct submodule_update_strategy update_strategy; struct list_objects_filter_options *filter_options; struct module_list list; + enum ref_storage_format ref_storage_format; int depth; int max_jobs; int single_branch; @@ -1996,6 +2029,7 @@ struct update_data { #define UPDATE_DATA_INIT { \ .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT, \ .list = MODULE_LIST_INIT, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ .recommend_shallow = -1, \ .references = STRING_LIST_INIT_DUP, \ .single_branch = -1, \ @@ -2005,6 +2039,7 @@ struct update_data { static void update_data_release(struct update_data *ud) { free(ud->displaypath); + submodule_update_strategy_release(&ud->update_strategy); module_list_release(&ud->list); } @@ -2131,6 +2166,9 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, expand_list_objects_filter_spec(suc->update_data->filter_options)); if (suc->update_data->require_init) strvec_push(&child->args, "--require-init"); + if (suc->update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&child->args, "--ref-format=%s", + ref_storage_format_to_name(suc->update_data->ref_storage_format)); strvec_pushl(&child->args, "--path", sub->path, NULL); strvec_pushl(&child->args, "--name", sub->name, NULL); strvec_pushl(&child->args, "--url", url, NULL); @@ -2302,7 +2340,14 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, strvec_pushf(&cp.args, "--depth=%d", depth); if (oid) { char *hex = oid_to_hex(oid); - char *remote = get_default_remote(); + char *remote; + int code; + + code = get_default_remote_submodule(module_path, &remote); + if (code) { + child_process_clear(&cp); + return code; + } strvec_pushl(&cp.args, remote, hex, NULL); free(remote); @@ -2565,6 +2610,9 @@ static void update_data_to_args(const struct update_data *update_data, for_each_string_list_item(item, &update_data->references) strvec_pushl(args, "--reference", item->string, NULL); } + if (update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(args, "--ref-format=%s", + ref_storage_format_to_name(update_data->ref_storage_format)); if (update_data->filter_options && update_data->filter_options->choice) strvec_pushf(args, "--filter=%s", expand_list_objects_filter_spec( @@ -2619,15 +2667,20 @@ static int update_submodule(struct update_data *update_data) if (!update_data->nofetch) { if (fetch_in_submodule(update_data->sm_path, update_data->depth, - 0, NULL)) + 0, NULL)) { + free(remote_ref); return die_message(_("Unable to fetch in submodule path '%s'"), update_data->sm_path); + } } if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, - remote_ref, &update_data->oid)) - return die_message(_("Unable to find %s revision in submodule path '%s'"), - remote_ref, update_data->sm_path); + remote_ref, &update_data->oid)) { + ret = die_message(_("Unable to find %s revision in submodule path '%s'"), + remote_ref, update_data->sm_path); + free(remote_ref); + return ret; + } free(remote_ref); } @@ -2733,13 +2786,15 @@ cleanup: return ret; } -static int module_update(int argc, const char **argv, const char *prefix) +static int module_update(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { struct pathspec pathspec = { 0 }; struct pathspec pathspec2 = { 0 }; struct update_data opt = UPDATE_DATA_INIT; struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; + const char *ref_storage_format = NULL; int ret; struct option module_update_options[] = { OPT__SUPER_PREFIX(&opt.super_prefix), @@ -2763,6 +2818,8 @@ static int module_update(int argc, const char **argv, const char *prefix) SM_UPDATE_REBASE), OPT_STRING_LIST(0, "reference", &opt.references, N_("repo"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &opt.dissociate, N_("use --reference only while cloning")), OPT_INTEGER(0, "depth", &opt.depth, @@ -2806,6 +2863,12 @@ static int module_update(int argc, const char **argv, const char *prefix) module_update_options); } + if (ref_storage_format) { + opt.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (opt.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } + opt.filter_options = &filter_options; opt.prefix = prefix; @@ -2856,7 +2919,8 @@ cleanup: return ret; } -static int push_check(int argc, const char **argv, const char *prefix UNUSED) +static int push_check(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { struct remote *remote; const char *superproject_head; @@ -2927,14 +2991,17 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED) rs->src); } } + refspec_clear(&refspec); + free_refs(local_refs); } free(head); return 0; } -static int absorb_git_dirs(int argc, const char **argv, const char *prefix) +static int absorb_git_dirs(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int i; struct pathspec pathspec = { 0 }; @@ -2967,7 +3034,8 @@ cleanup: return ret; } -static int module_set_url(int argc, const char **argv, const char *prefix) +static int module_set_url(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int quiet = 0, ret; const char *newurl; @@ -3006,7 +3074,8 @@ static int module_set_url(int argc, const char **argv, const char *prefix) return !!ret; } -static int module_set_branch(int argc, const char **argv, const char *prefix) +static int module_set_branch(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int opt_default = 0, ret; const char *opt_branch = NULL; @@ -3056,7 +3125,8 @@ static int module_set_branch(int argc, const char **argv, const char *prefix) return !!ret; } -static int module_create_branch(int argc, const char **argv, const char *prefix) +static int module_create_branch(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { enum branch_track track; int quiet = 0, force = 0, reflog = 0, dry_run = 0; @@ -3101,13 +3171,17 @@ struct add_data { const char *sm_name; const char *repo; const char *realrepo; + enum ref_storage_format ref_storage_format; int depth; unsigned int force: 1; unsigned int quiet: 1; unsigned int progress: 1; unsigned int dissociate: 1; }; -#define ADD_DATA_INIT { .depth = -1 } +#define ADD_DATA_INIT { \ + .depth = -1, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ +} static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path) { @@ -3201,6 +3275,7 @@ static int add_submodule(const struct add_data *add_data) string_list_append(&reference, p)->util = p; } + clone_data.ref_storage_format = add_data->ref_storage_format; clone_data.dissociate = add_data->dissociate; if (add_data->depth >= 0) clone_data.depth = add_data->depth; @@ -3362,10 +3437,12 @@ static void die_on_repo_without_commits(const char *path) strbuf_release(&sb); } -static int module_add(int argc, const char **argv, const char *prefix) +static int module_add(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { int force = 0, quiet = 0, progress = 0, dissociate = 0; struct add_data add_data = ADD_DATA_INIT; + const char *ref_storage_format = NULL; char *to_free = NULL; struct option options[] = { OPT_STRING('b', "branch", &add_data.branch, N_("branch"), @@ -3376,6 +3453,8 @@ static int module_add(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "progress", &progress, N_("force cloning progress")), OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")), OPT_STRING(0, "name", &add_data.sm_name, N_("name"), N_("sets the submodule's name to the given string " @@ -3402,6 +3481,12 @@ static int module_add(int argc, const char **argv, const char *prefix) if (argc == 0 || argc > 2) usage_with_options(usage, options); + if (ref_storage_format) { + add_data.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (add_data.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } + add_data.repo = argv[0]; if (argc == 1) add_data.sm_path = git_url_basename(add_data.repo, 0, 0); @@ -3483,7 +3568,10 @@ cleanup: return ret; } -int cmd_submodule__helper(int argc, const char **argv, const char *prefix) +int cmd_submodule__helper(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; const char *const usage[] = { @@ -3509,5 +3597,5 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix) }; argc = parse_options(argc, argv, prefix, options, usage, 0); - return fn(argc, argv, prefix); + return fn(argc, argv, prefix, repo); } diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index 81abdd170f..299d23d76a 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -41,7 +42,10 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i return 0; } -int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) +int cmd_symbolic_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int quiet = 0, delete = 0, shorten = 0, recurse = 1, ret = 0; const char *msg = NULL; diff --git a/builtin/tag.c b/builtin/tag.c index a1fb218512..affa14d659 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -5,7 +5,7 @@ * Carlos Rica <jasampler@gmail.com> * Based on git-tag.sh and mktag.c by Linus Torvalds. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -160,11 +160,11 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid, const struct git_hash_algo *compat = the_repository->compat_hash_algo; struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT; struct strbuf compat_buf = STRBUF_INIT; - const char *keyid = get_signing_key(); + char *keyid = get_signing_key(); int ret = -1; if (sign_buffer(buffer, &sig, keyid)) - return -1; + goto out; if (compat) { const struct git_hash_algo *algo = the_repository->hash_algo; @@ -190,6 +190,7 @@ out: strbuf_release(&sig); strbuf_release(&compat_sig); strbuf_release(&compat_buf); + free(keyid); return ret; } @@ -446,18 +447,10 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) return 0; } -static int strbuf_check_tag_ref(struct strbuf *sb, const char *name) -{ - if (name[0] == '-') - return -1; - - strbuf_reset(sb); - strbuf_addf(sb, "refs/tags/%s", name); - - return check_refname_format(sb->buf, 0); -} - -int cmd_tag(int argc, const char **argv, const char *prefix) +int cmd_tag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buf = STRBUF_INIT; struct strbuf ref = STRBUF_INIT; @@ -646,7 +639,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (repo_get_oid(the_repository, object_ref, &object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - if (strbuf_check_tag_ref(&ref, tag)) + if (check_tag_ref(&ref, tag)) die(_("'%s' is not a valid tag name."), tag); if (refs_read_ref(get_main_ref_store(the_repository), ref.buf, &prev)) @@ -677,7 +670,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) } transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction || ref_transaction_update(transaction, ref.buf, &object, &prev, NULL, NULL, @@ -702,6 +695,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) cleanup: ref_sorting_release(sorting); ref_filter_clear(&filter); + ref_format_clear(&format); strbuf_release(&buf); strbuf_release(&ref); strbuf_release(&reflog_msg); diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index c129e2bb6c..6da2825753 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -25,7 +26,10 @@ static char *create_temp_file(struct object_id *oid) return path; } -int cmd_unpack_file(int argc, const char **argv, const char *prefix UNUSED) +int cmd_unpack_file(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { struct object_id oid; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 08fa2a7a74..02b8d02f63 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "bulk-checkin.h" #include "config.h" @@ -601,7 +602,10 @@ static void unpack_all(void) die("unresolved deltas left after unpacking"); } -int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED) +int cmd_unpack_objects(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i; struct object_id oid; diff --git a/builtin/update-index.c b/builtin/update-index.c index d343416ae2..45b4a8b555 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "bulk-checkin.h" #include "config.h" @@ -22,7 +22,6 @@ #include "pathspec.h" #include "dir.h" #include "read-cache.h" -#include "repository.h" #include "setup.h" #include "sparse-index.h" #include "split-index.h" @@ -917,7 +916,10 @@ static enum parse_opt_result reupdate_callback( return 0; } -int cmd_update_index(int argc, const char **argv, const char *prefix) +int cmd_update_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int newfd, entries, has_errors = 0, nul_term_line = 0; enum uc_mode untracked_cache = UC_UNSPECIFIED; @@ -1156,7 +1158,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) end_odb_transaction(); if (split_index > 0) { - if (git_config_get_split_index() == 0) + if (repo_config_get_split_index(the_repository) == 0) warning(_("core.splitIndex is set to false; " "remove or change it, if you really want to " "enable split index")); @@ -1165,7 +1167,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) else add_split_index(the_repository->index); } else if (!split_index) { - if (git_config_get_split_index() == 1) + if (repo_config_get_split_index(the_repository) == 1) warning(_("core.splitIndex is set to true; " "remove or change it, if you really want to " "disable split index")); @@ -1194,7 +1196,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) "remove or change it, if you really want to " "enable the untracked cache")); add_untracked_cache(the_repository->index); - report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); + report(_("Untracked cache enabled for '%s'"), repo_get_work_tree(the_repository)); break; default: BUG("bad untracked_cache value: %d", untracked_cache); @@ -1239,7 +1241,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) if (newfd < 0) { if (refresh_args.flags & REFRESH_QUIET) exit(128); - unable_to_lock_die(get_index_file(), lock_error); + unable_to_lock_die(repo_get_index_file(the_repository), lock_error); } if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 6a6a2ff55d..670e7812d6 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -6,7 +7,6 @@ #include "object-name.h" #include "parse-options.h" #include "quote.h" -#include "repository.h" static const char * const git_update_ref_usage[] = { N_("git update-ref [<options>] -d <refname> [<old-oid>]"), @@ -274,7 +274,7 @@ static void parse_cmd_update(struct ref_transaction *transaction, } static void parse_cmd_symref_update(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { char *refname, *new_target, *old_arg; char *old_target = NULL; @@ -360,7 +360,7 @@ static void parse_cmd_create(struct ref_transaction *transaction, static void parse_cmd_symref_create(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; char *refname, *new_target; @@ -423,7 +423,7 @@ static void parse_cmd_delete(struct ref_transaction *transaction, static void parse_cmd_symref_delete(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; char *refname, *old_target; @@ -479,7 +479,7 @@ static void parse_cmd_verify(struct ref_transaction *transaction, } static void parse_cmd_symref_verify(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; struct object_id old_oid; @@ -612,7 +612,7 @@ static void update_refs_stdin(void) int i, j; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) die("%s", err.buf); @@ -680,7 +680,7 @@ static void update_refs_stdin(void) */ state = cmd->state; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) die("%s", err.buf); @@ -713,7 +713,10 @@ static void update_refs_stdin(void) strbuf_release(&input); } -int cmd_update_ref(int argc, const char **argv, const char *prefix) +int cmd_update_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *refname, *oldval; struct object_id oid, oldoid; diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index 1dc3971ede..6769611a02 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -9,7 +10,10 @@ static const char * const update_server_info_usage[] = { NULL }; -int cmd_update_server_info(int argc, const char **argv, const char *prefix) +int cmd_update_server_info(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force = 0; struct option options[] = { diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 1b09e5e1aa..9e9343f121 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -1,12 +1,12 @@ /* * Copyright (c) 2006 Franck Bui-Huu */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "archive.h" #include "path.h" #include "pkt-line.h" #include "sideband.h" -#include "repository.h" #include "run-command.h" #include "strvec.h" @@ -18,10 +18,14 @@ static const char deadchild[] = #define MAX_ARGS (64) -int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) +int cmd_upload_archive_writer(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strvec sent_argv = STRVEC_INIT; const char *arg_cmd = "argument "; + int ret; if (argc != 2 || !strcmp(argv[1], "-h")) usage(upload_archive_usage); @@ -46,8 +50,11 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) } /* parse all options sent by the client */ - return write_archive(sent_argv.nr, sent_argv.v, prefix, - the_repository, NULL, 1); + ret = write_archive(sent_argv.nr, sent_argv.v, prefix, + the_repository, NULL, 1); + + strvec_clear(&sent_argv); + return ret; } __attribute__((format (printf, 1, 2))) @@ -76,7 +83,10 @@ static ssize_t process_input(int child_fd, int band) return sz; } -int cmd_upload_archive(int argc, const char **argv, const char *prefix) +int cmd_upload_archive(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct child_process writer = CHILD_PROCESS_INIT; diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index 46d93278d9..dd63d6eadf 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -17,7 +17,10 @@ static const char * const upload_pack_usage[] = { NULL }; -int cmd_upload_pack(int argc, const char **argv, const char *prefix) +int cmd_upload_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *dir; int strict = 0; @@ -36,6 +39,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix) N_("interrupt transfer after <n> seconds of inactivity")), OPT_END() }; + unsigned enter_repo_flags = ENTER_REPO_ANY_OWNER_OK; packet_trace_identity("upload-pack"); disable_replace_refs(); @@ -51,7 +55,9 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix) dir = argv[0]; - if (!enter_repo(dir, strict)) + if (strict) + enter_repo_flags |= ENTER_REPO_STRICT; + if (!enter_repo(dir, enter_repo_flags)) die("'%s' does not appear to be a git repository", dir); switch (determine_protocol_version_server()) { diff --git a/builtin/var.c b/builtin/var.c index e30ff45be1..2ecaed51b4 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -3,7 +3,9 @@ * * Copyright (C) Eric Biederman, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "attr.h" #include "config.h" #include "editor.h" @@ -210,7 +212,10 @@ static int show_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_var(int argc, const char **argv, const char *prefix UNUSED) +int cmd_var(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { const struct git_var *git_var; char *val; diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 0d2b9aea2a..779b7988ca 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,11 +5,11 @@ * * Based on git-verify-tag */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "object-name.h" -#include "repository.h" #include "commit.h" #include "parse-options.h" #include "gpg-interface.h" @@ -51,7 +51,10 @@ static int verify_commit(const char *name, unsigned flags) return run_gpg_verify((struct commit *)obj, flags); } -int cmd_verify_commit(int argc, const char **argv, const char *prefix) +int cmd_verify_commit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c index 011dddd2dc..34e4ed715f 100644 --- a/builtin/verify-pack.c +++ b/builtin/verify-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -61,7 +62,10 @@ static const char * const verify_pack_usage[] = { NULL }; -int cmd_verify_pack(int argc, const char **argv, const char *prefix) +int cmd_verify_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int err = 0; unsigned int flags = 0; diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index c731e2f87b..a7f20618ff 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,6 +5,7 @@ * * Based on git-verify-tag.sh */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -19,7 +20,10 @@ static const char * const verify_tag_usage[] = { NULL }; -int cmd_verify_tag(int argc, const char **argv, const char *prefix) +int cmd_verify_tag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -65,5 +69,6 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) if (format.format) pretty_print_ref(name, &oid, &format); } + ref_format_clear(&format); return had_error; } diff --git a/builtin/worktree.c b/builtin/worktree.c index cec3ada6b0..0186d60ab1 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "advice.h" @@ -17,7 +18,6 @@ #include "read-cache-ll.h" #include "refs.h" #include "remote.h" -#include "repository.h" #include "run-command.h" #include "hook.h" #include "sigchain.h" @@ -120,12 +120,14 @@ struct add_opts { int quiet; int checkout; int orphan; + int relative_paths; const char *keep_locked; }; static int show_only; static int verbose; static int guess_remote; +static int use_relative_paths; static timestamp_t expire; static int git_worktree_config(const char *var, const char *value, @@ -134,6 +136,9 @@ static int git_worktree_config(const char *var, const char *value, if (!strcmp(var, "worktree.guessremote")) { guess_remote = git_config_bool(var, value); return 0; + } else if (!strcmp(var, "worktree.userelativepaths")) { + use_relative_paths = git_config_bool(var, value); + return 0; } return git_default_config(var, value, ctx, cb); @@ -219,7 +224,7 @@ static void prune_worktrees(void) } closedir(dir); - strbuf_add_absolute_path(&main_path, get_git_common_dir()); + strbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository)); /* massage main worktree absolute path to match 'gitdir' content */ strbuf_strip_suffix(&main_path, "/."); string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL)); @@ -231,7 +236,8 @@ static void prune_worktrees(void) strbuf_release(&reason); } -static int prune(int ac, const char **av, const char *prefix) +static int prune(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT__DRY_RUN(&show_only, N_("do not remove, show only")), @@ -414,7 +420,7 @@ static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; - struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; const char *name; struct strvec child_env = STRVEC_INIT; unsigned int counter = 0; @@ -432,7 +438,7 @@ static int add_worktree(const char *path, const char *refname, worktrees = NULL; /* is 'refname' a branch or commit? */ - if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && + if (!opts->detach && !check_branch_ref(&symref, refname) && refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) { is_branch = 1; if (!opts->force) @@ -490,11 +496,7 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - strbuf_realpath(&realpath, sb_git.buf, 1); - write_file(sb.buf, "%s", realpath.buf); - strbuf_realpath(&realpath, get_git_common_dir(), 1); - write_file(sb_git.buf, "gitdir: %s/worktrees/%s", - realpath.buf, name); + write_worktree_linking_files(sb_git, sb, opts->relative_paths); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -573,7 +575,7 @@ done: NULL); opt.dir = path; - ret = run_hooks_opt("post-checkout", &opt); + ret = run_hooks_opt(the_repository, "post-checkout", &opt); } strvec_clear(&child_env); @@ -582,7 +584,6 @@ done: strbuf_release(&sb_repo); strbuf_release(&sb_git); strbuf_release(&sb_name); - strbuf_release(&realpath); free_worktree(wt); return ret; } @@ -604,7 +605,7 @@ static void print_preparing_worktree_line(int detach, fprintf_ln(stderr, _("Preparing worktree (new branch '%s')"), new_branch); } else { struct strbuf s = STRBUF_INIT; - if (!detach && !strbuf_check_branch_ref(&s, branch) && + if (!detach && !check_branch_ref(&s, branch) && refs_ref_exists(get_main_ref_store(the_repository), s.buf)) fprintf_ln(stderr, _("Preparing worktree (checking out '%s')"), branch); @@ -626,6 +627,7 @@ static void print_preparing_worktree_line(int detach, * Returns 0 on failure and non-zero on success. */ static int first_valid_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data UNUSED) @@ -744,7 +746,7 @@ static char *dwim_branch(const char *path, char **new_branch) char *branchname = xstrndup(s, n); struct strbuf ref = STRBUF_INIT; - branch_exists = !strbuf_check_branch_ref(&ref, branchname) && + branch_exists = !check_branch_ref(&ref, branchname) && refs_ref_exists(get_main_ref_store(the_repository), ref.buf); strbuf_release(&ref); @@ -760,7 +762,8 @@ static char *dwim_branch(const char *path, char **new_branch) return NULL; } -static int add(int ac, const char **av, const char *prefix) +static int add(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { struct add_opts opts; const char *new_branch_force = NULL; @@ -793,12 +796,15 @@ static int add(int ac, const char **av, const char *prefix) PARSE_OPT_NOARG | PARSE_OPT_OPTARG), OPT_BOOL(0, "guess-remote", &guess_remote, N_("try to match the new branch name with a remote-tracking branch")), + OPT_BOOL(0, "relative-paths", &opts.relative_paths, + N_("use relative paths for worktrees")), OPT_END() }; int ret; memset(&opts, 0, sizeof(opts)); opts.checkout = 1; + opts.relative_paths = use_relative_paths; ac = parse_options(ac, av, prefix, options, git_worktree_add_usage, 0); if (!!opts.detach + !!new_branch + !!new_branch_force > 1) die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach"); @@ -837,7 +843,7 @@ static int add(int ac, const char **av, const char *prefix) new_branch = new_branch_force; if (!opts.force && - !strbuf_check_branch_ref(&symref, new_branch) && + !check_branch_ref(&symref, new_branch) && refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) die_if_checked_out(symref.buf, 0); strbuf_release(&symref); @@ -1036,7 +1042,8 @@ static void pathsort(struct worktree **wt) QSORT(wt, n, pathcmp); } -static int list(int ac, const char **av, const char *prefix) +static int list(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { int porcelain = 0; int line_terminator = '\n'; @@ -1081,7 +1088,8 @@ static int list(int ac, const char **av, const char *prefix) return 0; } -static int lock_worktree(int ac, const char **av, const char *prefix) +static int lock_worktree(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { const char *reason = "", *old_reason; struct option options[] = { @@ -1116,7 +1124,8 @@ static int lock_worktree(int ac, const char **av, const char *prefix) return 0; } -static int unlock_worktree(int ac, const char **av, const char *prefix) +static int unlock_worktree(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { struct option options[] = { OPT_END() @@ -1147,14 +1156,14 @@ static void validate_no_submodules(const struct worktree *wt) struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; - if (is_directory(worktree_git_path(wt, "modules"))) { + if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* * There could be false positives, e.g. the "modules" * directory exists but is empty. But it's a rare case and * this simpler check is probably good enough for now. */ found_submodules = 1; - } else if (read_index_from(&istate, worktree_git_path(wt, "index"), + } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), get_worktree_git_dir(wt)) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; @@ -1179,13 +1188,16 @@ static void validate_no_submodules(const struct worktree *wt) die(_("working trees containing submodules cannot be moved or removed")); } -static int move_worktree(int ac, const char **av, const char *prefix) +static int move_worktree(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { int force = 0; struct option options[] = { OPT__FORCE(&force, N_("force move even if worktree is dirty or locked"), PARSE_OPT_NOCOMPLETE), + OPT_BOOL(0, "relative-paths", &use_relative_paths, + N_("use relative paths for worktrees")), OPT_END() }; struct worktree **worktrees, *wt; @@ -1238,7 +1250,7 @@ static int move_worktree(int ac, const char **av, const char *prefix) if (rename(wt->path, dst.buf) == -1) die_errno(_("failed to move '%s' to '%s'"), wt->path, dst.buf); - update_worktree_location(wt, dst.buf); + update_worktree_location(wt, dst.buf, use_relative_paths); strbuf_release(&dst); free_worktrees(worktrees); @@ -1309,7 +1321,8 @@ static int delete_git_work_tree(struct worktree *wt) return ret; } -static int remove_worktree(int ac, const char **av, const char *prefix) +static int remove_worktree(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { int force = 0; struct option options[] = { @@ -1374,11 +1387,14 @@ static void report_repair(int iserr, const char *path, const char *msg, void *cb } } -static int repair(int ac, const char **av, const char *prefix) +static int repair(int ac, const char **av, const char *prefix, + struct repository *repo UNUSED) { const char **p; const char *self[] = { ".", NULL }; struct option options[] = { + OPT_BOOL(0, "relative-paths", &use_relative_paths, + N_("use relative paths for worktrees")), OPT_END() }; int rc = 0; @@ -1386,12 +1402,15 @@ static int repair(int ac, const char **av, const char *prefix) ac = parse_options(ac, av, prefix, options, git_worktree_repair_usage, 0); p = ac > 0 ? av : self; for (; *p; p++) - repair_worktree_at_path(*p, report_repair, &rc); - repair_worktrees(report_repair, &rc); + repair_worktree_at_path(*p, report_repair, &rc, use_relative_paths); + repair_worktrees(report_repair, &rc, use_relative_paths); return rc; } -int cmd_worktree(int ac, const char **av, const char *prefix) +int cmd_worktree(int ac, + const char **av, + const char *prefix, + struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { @@ -1416,5 +1435,5 @@ int cmd_worktree(int ac, const char **av, const char *prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - return fn(ac, av, prefix); + return fn(ac, av, prefix, repo); } diff --git a/builtin/write-tree.c b/builtin/write-tree.c index 8c75b4609b..43f233e69b 100644 --- a/builtin/write-tree.c +++ b/builtin/write-tree.c @@ -3,23 +3,24 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "tree.h" #include "cache-tree.h" #include "parse-options.h" -#include "repository.h" static const char * const write_tree_usage[] = { N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"), NULL }; -int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix) +int cmd_write_tree(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int flags = 0, ret; const char *tree_prefix = NULL; @@ -44,7 +45,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - ret = write_index_as_tree(&oid, the_repository->index, get_index_file(), + ret = write_index_as_tree(&oid, the_repository->index, + repo_get_index_file(the_repository), flags, tree_prefix); switch (ret) { case 0: diff --git a/bulk-checkin.c b/bulk-checkin.c index da8673199b..2753d5bbe4 100644 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@ -61,6 +61,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) if (state->nr_written == 0) { close(state->f->fd); + free_hashfile(state->f); unlink(state->pack_tmp_name); goto clear_exit; } else if (state->nr_written == 1) { @@ -74,7 +75,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) close(fd); } - strbuf_addf(&packname, "%s/pack/pack-%s.", get_object_directory(), + strbuf_addf(&packname, "%s/pack/pack-%s.", repo_get_object_directory(the_repository), hash_to_hex(hash)); finish_tmp_packfile(&packname, state->pack_tmp_name, state->written, state->nr_written, @@ -83,6 +84,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) free(state->written[i]); clear_exit: + free(state->pack_tmp_name); free(state->written); memset(state, 0, sizeof(*state)); @@ -111,7 +113,7 @@ static void flush_batch_fsync(void) * to ensure that the data in each new object file is durable before * the final name is visible. */ - strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", get_object_directory()); + strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", repo_get_object_directory(the_repository)); temp = xmks_tempfile(temp_path.buf); fsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp)); delete_tempfile(&temp); diff --git a/bundle-uri.c b/bundle-uri.c index 1e0ee156ba..cdf9e4f9e1 100644 --- a/bundle-uri.c +++ b/bundle-uri.c @@ -4,7 +4,6 @@ #include "bundle-uri.h" #include "bundle.h" #include "copy.h" -#include "environment.h" #include "gettext.h" #include "refs.h" #include "run-command.h" @@ -13,6 +12,8 @@ #include "config.h" #include "fetch-pack.h" #include "remote.h" +#include "trace2.h" +#include "object-store-ll.h" static struct { enum bundle_list_heuristic heuristic; @@ -366,18 +367,27 @@ static int unbundle_from_file(struct repository *r, const char *file) struct string_list_item *refname; struct strbuf bundle_ref = STRBUF_INIT; size_t bundle_prefix_len; + struct unbundle_opts opts = { + .flags = VERIFY_BUNDLE_QUIET | + (fetch_pack_fsck_objects() ? VERIFY_BUNDLE_FSCK : 0), + }; - if ((bundle_fd = read_bundle_header(file, &header)) < 0) - return 1; + bundle_fd = read_bundle_header(file, &header); + if (bundle_fd < 0) { + result = 1; + goto cleanup; + } /* * Skip the reachability walk here, since we will be adding * a reachable ref pointing to the new tips, which will reach * the prerequisite commits. */ - if ((result = unbundle(r, &header, bundle_fd, NULL, - VERIFY_BUNDLE_QUIET | (fetch_pack_fsck_objects() ? VERIFY_BUNDLE_FSCK : 0)))) - return 1; + result = unbundle(r, &header, bundle_fd, NULL, &opts); + if (result) { + result = 1; + goto cleanup; + } /* * Convert all refs/heads/ from the bundle into refs/bundles/ @@ -406,6 +416,8 @@ static int unbundle_from_file(struct repository *r, const char *file) 0, UPDATE_REFS_MSG_ON_ERR); } +cleanup: + strbuf_release(&bundle_ref); bundle_header_release(&header); return result; } @@ -799,6 +811,8 @@ int fetch_bundle_uri(struct repository *r, const char *uri, .id = xstrdup(""), }; + trace2_region_enter("fetch", "fetch-bundle-uri", the_repository); + init_bundle_list(&list); /* @@ -824,6 +838,7 @@ cleanup: for_all_bundles_in_list(&list, unlink_bundle, NULL); clear_bundle_list(&list); clear_remote_bundle_info(&bundle, NULL); + trace2_region_leave("fetch", "fetch-bundle-uri", the_repository); return result; } @@ -89,7 +89,12 @@ int read_bundle_header_fd(int fd, struct bundle_header *header, goto abort; } - header->hash_algo = the_hash_algo; + /* + * The default hash format for bundles is SHA1, unless told otherwise + * by an "object-format=" capability, which is being handled in + * `parse_capability()`. + */ + header->hash_algo = &hash_algos[GIT_HASH_SHA1]; /* The bundle header ends with an empty line */ while (!strbuf_getwholeline_fd(&buf, fd, '\n') && @@ -623,11 +628,15 @@ out: int unbundle(struct repository *r, struct bundle_header *header, int bundle_fd, struct strvec *extra_index_pack_args, - enum verify_bundle_flags flags) + struct unbundle_opts *opts) { struct child_process ip = CHILD_PROCESS_INIT; + struct unbundle_opts opts_fallback = { 0 }; - if (verify_bundle(r, header, flags)) + if (!opts) + opts = &opts_fallback; + + if (verify_bundle(r, header, opts->flags)) return -1; strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL); @@ -636,13 +645,12 @@ int unbundle(struct repository *r, struct bundle_header *header, if (header->filter.choice) strvec_push(&ip.args, "--promisor=from-bundle"); - if (flags & VERIFY_BUNDLE_FSCK) - strvec_push(&ip.args, "--fsck-objects"); + if (opts->flags & VERIFY_BUNDLE_FSCK) + strvec_pushf(&ip.args, "--fsck-objects%s", + opts->fsck_msg_types ? opts->fsck_msg_types : ""); - if (extra_index_pack_args) { + if (extra_index_pack_args) strvec_pushv(&ip.args, extra_index_pack_args->v); - strvec_clear(extra_index_pack_args); - } ip.in = bundle_fd; ip.no_stdout = 1; @@ -39,6 +39,17 @@ enum verify_bundle_flags { int verify_bundle(struct repository *r, struct bundle_header *header, enum verify_bundle_flags flags); +struct unbundle_opts { + enum verify_bundle_flags flags; + /* + * fsck_msg_types may optionally contain fsck message severity + * configuration. If present, this configuration gets directly appended + * to a '--fsck-objects' option and therefore must be prefixed with '='. + * (E.g. "=missingEmail=ignore,gitmodulesUrl=ignore") + */ + const char *fsck_msg_types; +}; + /** * Unbundle after reading the header with read_bundle_header(). * @@ -49,12 +60,12 @@ int verify_bundle(struct repository *r, struct bundle_header *header, * (e.g. "-v" for verbose/progress), NULL otherwise. The provided * "extra_index_pack_args" (if any) will be strvec_clear()'d for you. * - * Before unbundling, this method will call verify_bundle() with the - * given 'flags'. + * Before unbundling, this method will call verify_bundle() with 'flags' + * provided in 'opts'. */ int unbundle(struct repository *r, struct bundle_header *header, int bundle_fd, struct strvec *extra_index_pack_args, - enum verify_bundle_flags flags); + struct unbundle_opts *opts); int list_bundle_refs(struct bundle_header *header, int argc, const char **argv); diff --git a/cache-tree.c b/cache-tree.c index 50610c3f3c..c595e86120 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -1,7 +1,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" -#include "environment.h" +#include "gettext.h" #include "hex.h" #include "lockfile.h" #include "tree.h" @@ -12,6 +12,7 @@ #include "object-store-ll.h" #include "read-cache-ll.h" #include "replace-object.h" +#include "repository.h" #include "promisor-remote.h" #include "trace.h" #include "trace2.h" @@ -725,7 +726,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state, hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR); - entries = read_index_from(index_state, index_path, get_git_dir()); + entries = read_index_from(index_state, index_path, + repo_get_git_dir(the_repository)); if (entries < 0) { ret = WRITE_TREE_UNREADABLE_INDEX; goto out; @@ -864,15 +866,15 @@ int cache_tree_matches_traversal(struct cache_tree *root, return 0; } -static void verify_one_sparse(struct index_state *istate, - struct strbuf *path, - int pos) +static int verify_one_sparse(struct index_state *istate, + struct strbuf *path, + int pos) { struct cache_entry *ce = istate->cache[pos]; - if (!S_ISSPARSEDIR(ce->ce_mode)) - BUG("directory '%s' is present in index, but not sparse", - path->buf); + return error(_("directory '%s' is present in index, but not sparse"), + path->buf); + return 0; } /* @@ -881,6 +883,7 @@ static void verify_one_sparse(struct index_state *istate, * 1 - Restart verification - a call to ensure_full_index() freed the cache * tree that is being verified and verification needs to be restarted from * the new toplevel cache tree. + * -1 - Verification failed. */ static int verify_one(struct repository *r, struct index_state *istate, @@ -890,18 +893,23 @@ static int verify_one(struct repository *r, int i, pos, len = path->len; struct strbuf tree_buf = STRBUF_INIT; struct object_id new_oid; + int ret; for (i = 0; i < it->subtree_nr; i++) { strbuf_addf(path, "%s/", it->down[i]->name); - if (verify_one(r, istate, it->down[i]->cache_tree, path)) - return 1; + ret = verify_one(r, istate, it->down[i]->cache_tree, path); + if (ret) + goto out; + strbuf_setlen(path, len); } if (it->entry_count < 0 || /* no verification on tests (t7003) that replace trees */ - lookup_replace_object(r, &it->oid) != &it->oid) - return 0; + lookup_replace_object(r, &it->oid) != &it->oid) { + ret = 0; + goto out; + } if (path->len) { /* @@ -911,12 +919,14 @@ static int verify_one(struct repository *r, */ int is_sparse = istate->sparse_index; pos = index_name_pos(istate, path->buf, path->len); - if (is_sparse && !istate->sparse_index) - return 1; + if (is_sparse && !istate->sparse_index) { + ret = 1; + goto out; + } if (pos >= 0) { - verify_one_sparse(istate, path, pos); - return 0; + ret = verify_one_sparse(istate, path, pos); + goto out; } pos = -pos - 1; @@ -924,6 +934,11 @@ static int verify_one(struct repository *r, pos = 0; } + if (it->entry_count + pos > istate->cache_nr) { + ret = error(_("corrupted cache-tree has entries not present in index")); + goto out; + } + i = 0; while (i < it->entry_count) { struct cache_entry *ce = istate->cache[pos + i]; @@ -934,16 +949,23 @@ static int verify_one(struct repository *r, unsigned mode; int entlen; - if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE)) - BUG("%s with flags 0x%x should not be in cache-tree", - ce->name, ce->ce_flags); + if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE)) { + ret = error(_("%s with flags 0x%x should not be in cache-tree"), + ce->name, ce->ce_flags); + goto out; + } + name = ce->name + path->len; slash = strchr(name, '/'); if (slash) { entlen = slash - name; + sub = find_subtree(it, ce->name + path->len, entlen, 0); - if (!sub || sub->cache_tree->entry_count < 0) - BUG("bad subtree '%.*s'", entlen, name); + if (!sub || sub->cache_tree->entry_count < 0) { + ret = error(_("bad subtree '%.*s'"), entlen, name); + goto out; + } + oid = &sub->cache_tree->oid; mode = S_IFDIR; i += sub->cache_tree->entry_count; @@ -956,27 +978,50 @@ static int verify_one(struct repository *r, strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0'); strbuf_add(&tree_buf, oid->hash, r->hash_algo->rawsz); } + hash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, OBJ_TREE, &new_oid); - if (!oideq(&new_oid, &it->oid)) - BUG("cache-tree for path %.*s does not match. " - "Expected %s got %s", len, path->buf, - oid_to_hex(&new_oid), oid_to_hex(&it->oid)); + + if (!oideq(&new_oid, &it->oid)) { + ret = error(_("cache-tree for path %.*s does not match. " + "Expected %s got %s"), len, path->buf, + oid_to_hex(&new_oid), oid_to_hex(&it->oid)); + goto out; + } + + ret = 0; +out: strbuf_setlen(path, len); strbuf_release(&tree_buf); - return 0; + return ret; } -void cache_tree_verify(struct repository *r, struct index_state *istate) +int cache_tree_verify(struct repository *r, struct index_state *istate) { struct strbuf path = STRBUF_INIT; + int ret; - if (!istate->cache_tree) - return; - if (verify_one(r, istate, istate->cache_tree, &path)) { + if (!istate->cache_tree) { + ret = 0; + goto out; + } + + ret = verify_one(r, istate, istate->cache_tree, &path); + if (ret < 0) + goto out; + if (ret > 0) { strbuf_reset(&path); - if (verify_one(r, istate, istate->cache_tree, &path)) + + ret = verify_one(r, istate, istate->cache_tree, &path); + if (ret < 0) + goto out; + if (ret > 0) BUG("ensure_full_index() called twice while verifying cache tree"); } + + ret = 0; + +out: strbuf_release(&path); + return ret; } diff --git a/cache-tree.h b/cache-tree.h index faae88be63..b82c4963e7 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -33,7 +33,7 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size); int cache_tree_fully_valid(struct cache_tree *); int cache_tree_update(struct index_state *, int); -void cache_tree_verify(struct repository *, struct index_state *); +int cache_tree_verify(struct repository *, struct index_state *); /* bitmasks to write_index_as_tree flags */ #define WRITE_TREE_MISSING_OK 1 @@ -12,7 +12,7 @@ static struct cb_node *cb_node_of(const void *p) return (struct cb_node *)((uintptr_t)p - 1); } -/* locate the best match, does not do a final comparision */ +/* locate the best match, does not do a final comparison */ static struct cb_node *cb_internal_best_match(struct cb_node *p, const uint8_t *k, size_t klen) { diff --git a/ci/check-whitespace.sh b/ci/check-whitespace.sh index db399097a5..c40804394c 100755 --- a/ci/check-whitespace.sh +++ b/ci/check-whitespace.sh @@ -9,7 +9,7 @@ baseCommit=$1 outputFile=$2 url=$3 -if test "$#" -ne 1 && test "$#" -ne 3 +if test "$#" -ne 1 && test "$#" -ne 3 || test -z "$1" then echo "USAGE: $0 <BASE_COMMIT> [<OUTPUT_FILE> <URL>]" exit 1 @@ -21,6 +21,12 @@ commitText= commitTextmd= goodParent= +if ! git rev-parse --quiet --verify "${baseCommit}" +then + echo "Invalid <BASE_COMMIT> '${baseCommit}'" + exit 1 +fi + while read dash sha etc do case "${dash}" in @@ -67,7 +73,7 @@ then goodParent=${baseCommit: 0:7} fi - echo "A whitespace issue was found in onen of more of the commits." + echo "A whitespace issue was found in one or more of the commits." echo "Run the following command to resolve whitespace issues:" echo "git rebase --whitespace=fix ${goodParent}" diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh index 6ec0f85972..d020cb7aa5 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -7,7 +7,7 @@ begin_group "Install dependencies" -P4WHENCE=https://cdist2.perforce.com/perforce/r21.2 +P4WHENCE=https://cdist2.perforce.com/perforce/r23.2 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION JGITWHENCE=https://repo.eclipse.org/content/groups/releases//org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh @@ -29,41 +29,54 @@ alpine-*) apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \ bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null ;; -fedora-*) +fedora-*|almalinux-*) dnf -yq update >/dev/null && dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null ;; -ubuntu-*) +ubuntu-*|ubuntu32-*|debian-*) # Required so that apt doesn't wait for user input on certain packages. export DEBIAN_FRONTEND=noninteractive + case "$distro" in + ubuntu-*) + SVN='libsvn-perl subversion' + LANGUAGES='language-pack-is' + ;; + ubuntu32-*) + SVN= + LANGUAGES='language-pack-is' + ;; + *) + SVN='libsvn-perl subversion' + LANGUAGES='locales-all' + ;; + esac + sudo apt-get -q update sudo apt-get -q -y install \ - language-pack-is libsvn-perl apache2 cvs cvsps git gnupg subversion \ + $LANGUAGES apache2 cvs cvsps git gnupg $SVN \ 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 \ ${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE - mkdir --parents "$CUSTOM_PATH" - wget --quiet --directory-prefix="$CUSTOM_PATH" \ - "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4" - chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4" + case "$distro" in + ubuntu-*) + mkdir --parents "$CUSTOM_PATH" - wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" - tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \ - -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs" - rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" + wget --quiet --directory-prefix="$CUSTOM_PATH" \ + "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4" + chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4" - wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit" - chmod a+x "$CUSTOM_PATH/jgit" - ;; -ubuntu32-*) - sudo linux32 --32bit i386 sh -c ' - apt update >/dev/null && - apt install -y build-essential libcurl4-openssl-dev \ - libssl-dev libexpat-dev gettext python >/dev/null - ' + wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" + tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \ + -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs" + rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" + + wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit" + chmod a+x "$CUSTOM_PATH/jgit" + ;; + esac ;; macos-*) export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 @@ -87,6 +100,10 @@ macos-*) esac case "$jobname" in +ClangFormat) + sudo apt-get -q update + sudo apt-get -q -y install clang-format + ;; StaticAnalysis) sudo apt-get -q update sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \ @@ -103,6 +120,7 @@ Documentation) test -n "$ALREADY_HAVE_ASCIIDOCTOR" || sudo gem install --version 1.5.8 asciidoctor + sudo gem install concurrent-ruby ;; esac diff --git a/ci/install-sdk.ps1 b/ci/install-sdk.ps1 new file mode 100755 index 0000000000..66f24838a4 --- /dev/null +++ b/ci/install-sdk.ps1 @@ -0,0 +1,12 @@ +param( + [string]$directory='git-sdk', + [string]$url='https://github.com/git-for-windows/git-sdk-64/releases/download/ci-artifacts/git-sdk-x86_64-minimal.zip' +) + +Invoke-WebRequest "$url" -OutFile git-sdk.zip +Expand-Archive -LiteralPath git-sdk.zip -DestinationPath "$directory" +Remove-Item -Path git-sdk.zip + +New-Item -Path .git/info -ItemType Directory -Force +New-Item -Path .git/info/exclude -ItemType File -Force +Add-Content -Path .git/info/exclude -Value "/$directory" @@ -62,7 +62,7 @@ trap "end_group 'CI setup'" EXIT # something went wrong. # # We already enabled tracing executed commands earlier. This helps by showing -# how # environment variables are set and and dependencies are installed. +# how # environment variables are set and dependencies are installed. set -e skip_branch_tip_with_tag () { @@ -250,8 +250,13 @@ then CI_TYPE=gitlab-ci CI_BRANCH="$CI_COMMIT_REF_NAME" CI_COMMIT="$CI_COMMIT_SHA" - case "$CI_JOB_IMAGE" in - macos-*) + + case "$OS,$CI_JOB_IMAGE" in + Windows_NT,*) + CI_OS_NAME=windows + JOBS=$NUMBER_OF_PROCESSORS + ;; + *,macos-*) # GitLab CI has Python installed via multiple package managers, # most notably via asdf and Homebrew. Ensure that our builds # pick up the Homebrew one by prepending it to our PATH as the @@ -259,9 +264,12 @@ then export PATH="$(brew --prefix)/bin:$PATH" CI_OS_NAME=osx + JOBS=$(nproc) + ;; + *,alpine:*|*,fedora:*|*,ubuntu:*) + CI_OS_NAME=linux + JOBS=$(nproc) ;; - alpine:*|fedora:*|ubuntu:*) - CI_OS_NAME=linux;; *) echo "Could not identify OS image" >&2 env >&2 @@ -272,6 +280,7 @@ then CI_JOB_ID="$CI_JOB_ID" CC="${CC_PACKAGE:-${CC:-gcc}}" DONT_SKIP_TAGS=t + handle_failed_tests () { create_failed_test_artifacts return 1 @@ -280,7 +289,6 @@ then cache_dir="$HOME/none" distro=$(echo "$CI_JOB_IMAGE" | tr : -) - JOBS=$(nproc) else echo "Could not identify CI type" >&2 env >&2 @@ -336,7 +344,14 @@ ubuntu-*) fi MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE" - export GIT_TEST_HTTPD=true + case "$distro" in + ubuntu-16.04) + # Apache is too old for HTTP/2. + ;; + *) + export GIT_TEST_HTTPD=true + ;; + esac # The Linux build installs the defined dependency versions below. # The OS X build installs much more recent versions, whichever @@ -369,7 +384,6 @@ linux-musl) ;; linux-leaks|linux-reftable-leaks) export SANITIZE=leak - export GIT_TEST_PASSING_SANITIZE_LEAK=true ;; linux-asan-ubsan) export SANITIZE=address,undefined diff --git a/ci/run-build-and-minimal-fuzzers.sh b/ci/run-build-and-minimal-fuzzers.sh index af8065f349..e7b97952e7 100755 --- a/ci/run-build-and-minimal-fuzzers.sh +++ b/ci/run-build-and-minimal-fuzzers.sh @@ -13,7 +13,18 @@ group "Build fuzzers" make \ LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \ fuzz-all -for fuzzer in commit-graph config date pack-headers pack-idx ; do +fuzzers=" +commit-graph +config +credential-from-url-gently +date +pack-headers +pack-idx +parse-attr-line +url-decode-mem +" + +for fuzzer in $fuzzers; do begin_group "fuzz-$fuzzer" ./oss-fuzz/fuzz-$fuzzer -verbosity=0 -runs=1 || exit 1 end_group "fuzz-$fuzzer" diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 98dda42045..2e28d02b20 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -25,7 +25,7 @@ linux-TEST-vars) export GIT_TEST_COMMIT_GRAPH=1 export GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1 export GIT_TEST_MULTI_PACK_INDEX=1 - export GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=1 + export GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=1 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master export GIT_TEST_NO_WRITE_REV_INDEX=1 export GIT_TEST_CHECKOUT_WORKERS=2 diff --git a/ci/run-docker-build.sh b/ci/run-docker-build.sh deleted file mode 100755 index 6cd832efb9..0000000000 --- a/ci/run-docker-build.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# -# Build and test Git inside container -# -# Usage: -# run-docker-build.sh <host-user-id> -# - -set -ex - -if test $# -ne 1 || test -z "$1" -then - echo >&2 "usage: run-docker-build.sh <host-user-id>" - exit 1 -fi - -case "$jobname" in -linux32) - switch_cmd="linux32 --32bit i386" - ;; -linux-musl) - switch_cmd= - useradd () { adduser -D "$@"; } - ;; -*) - exit 1 - ;; -esac - -"${0%/*}/install-docker-dependencies.sh" - -# If this script runs inside a docker container, then all commands are -# usually executed as root. Consequently, the host user might not be -# able to access the test output files. -# If a non 0 host user id is given, then create a user "ci" with that -# user id to make everything accessible to the host user. -HOST_UID=$1 -if test $HOST_UID -eq 0 -then - # Just in case someone does want to run the test suite as root. - CI_USER=root -else - CI_USER=ci - if test "$(id -u $CI_USER 2>/dev/null)" = $HOST_UID - then - echo "user '$CI_USER' already exists with the requested ID $HOST_UID" - else - useradd -u $HOST_UID $CI_USER - fi -fi - -# Build and test -command $switch_cmd su -m -l $CI_USER -c " - set -ex - export DEVELOPER='$DEVELOPER' - export DEFAULT_TEST_TARGET='$DEFAULT_TEST_TARGET' - export GIT_PROVE_OPTS='$GIT_PROVE_OPTS' - export GIT_TEST_OPTS='$GIT_TEST_OPTS' - export GIT_TEST_CLONE_2GB='$GIT_TEST_CLONE_2GB' - export MAKEFLAGS='$MAKEFLAGS' - export cache_dir='$cache_dir' - cd /usr/src/git - test -n '$cache_dir' && ln -s '$cache_dir/.prove' t/.prove - make - make test -" diff --git a/ci/run-docker.sh b/ci/run-docker.sh deleted file mode 100755 index af89d1624a..0000000000 --- a/ci/run-docker.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# -# Download and run Docker image to build and test Git -# - -. ${0%/*}/lib.sh - -case "$jobname" in -linux32) - CI_CONTAINER="daald/ubuntu32:xenial" - ;; -linux-musl) - CI_CONTAINER=alpine - ;; -*) - exit 1 - ;; -esac - -docker pull "$CI_CONTAINER" - -# Use the following command to debug the docker build locally: -# <host-user-id> must be 0 if podman is used as drop-in replacement for docker -# $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/sh "$CI_CONTAINER" -# root@container:/# export jobname=<jobname> -# root@container:/# /usr/src/git/ci/run-docker-build.sh <host-user-id> - -container_cache_dir=/tmp/container-cache - -docker run \ - --interactive \ - --env DEVELOPER \ - --env DEFAULT_TEST_TARGET \ - --env GIT_PROVE_OPTS \ - --env GIT_TEST_OPTS \ - --env GIT_TEST_CLONE_2GB \ - --env MAKEFLAGS \ - --env jobname \ - --env cache_dir="$container_cache_dir" \ - --volume "${PWD}:/usr/src/git" \ - --volume "$cache_dir:$container_cache_dir" \ - "$CI_CONTAINER" \ - /usr/src/git/ci/run-docker-build.sh $(id -u $USER) - -check_unignored_build_artifacts - -save_good_tree diff --git a/ci/run-style-check.sh b/ci/run-style-check.sh new file mode 100755 index 0000000000..6cd4b1d934 --- /dev/null +++ b/ci/run-style-check.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Perform style check +# + +baseCommit=$1 + +# Remove optional braces of control statements (if, else, for, and while) +# according to the LLVM coding style. This avoids braces on simple +# single-statement bodies of statements but keeps braces if one side of +# if/else if/.../else cascade has multi-statement body. +# +# As this rule comes with a warning [1], we want to experiment with it +# before adding it in-tree. since the CI job for the style check is allowed +# to fail, appending the rule here allows us to validate its efficacy. +# While also ensuring that end-users are not affected directly. +# +# [1]: https://clang.llvm.org/docs/ClangFormatStyleOptions.html#removebracesllvm +{ + cat .clang-format + echo "RemoveBracesLLVM: true" +} >/tmp/clang-format-rules + +git clang-format --style=file:/tmp/clang-format-rules \ + --diff --extensions c,h "$baseCommit" diff --git a/combine-diff.c b/combine-diff.c index 829a44e416..33d0ed7097 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -1185,7 +1185,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, result_file.ptr = result; result_file.size = result_size; - /* Even p_lno[cnt+1] is valid -- that is for the end line number + /* + * Even p_lno[cnt+1] is valid -- that is for the end line number * for deletion hunk at the end. */ CALLOC_ARRAY(sline[0].p_lno, st_mult(st_add(cnt, 2), num_parent)); @@ -1220,7 +1221,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } free(result); - for (lno = 0; lno < cnt; lno++) { + for (lno = 0; lno < cnt + 2; lno++) { if (sline[lno].lost) { struct lline *ll = sline[lno].lost; while (ll) { @@ -1393,9 +1394,8 @@ static struct combine_diff_path *find_paths_generic(const struct object_id *oid, { struct combine_diff_path *paths = NULL; int i, num_parent = parents->nr; - int output_format = opt->output_format; - const char *orderfile = opt->orderfile; + char *orderfile = opt->orderfile; opt->output_format = DIFF_FORMAT_NO_OUTPUT; /* tell diff_tree to emit paths in sorted (=tree) order */ diff --git a/commit-graph.c b/commit-graph.c index 79b0e72cc4..e2e2083951 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1847,6 +1847,7 @@ struct refs_cb_data { }; static int add_ref_to_set(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -1913,7 +1914,7 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx, struct packed_git *p; strbuf_setlen(&packname, dirlen); strbuf_addstr(&packname, pack_indexes->items[i].string); - p = add_packed_git(packname.buf, packname.len, 1); + p = add_packed_git(ctx->r, packname.buf, packname.len, 1); if (!p) { ret = error(_("error adding pack %s"), packname.buf); goto cleanup; @@ -1959,7 +1960,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx) ctx->progress = start_delayed_progress( _("Finding commits for commit graph among packed objects"), ctx->approx_nr_objects); - for_each_packed_object(add_packed_commits, ctx, + for_each_packed_object(ctx->r, add_packed_commits, ctx, FOR_EACH_OBJECT_PACK_ORDER); if (ctx->progress_done < ctx->approx_nr_objects) display_progress(ctx->progress, ctx->approx_nr_objects); @@ -2054,7 +2055,6 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) } if (safe_create_leading_directories(ctx->graph_name)) { - UNLEAK(ctx->graph_name); error(_("unable to create leading directories of %s"), ctx->graph_name); return -1; diff --git a/commit-reach.c b/commit-reach.c index 02f8218b8e..c3518aa360 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -1229,3 +1229,129 @@ done: repo_clear_commit_marks(r, SEEN); free_commit_list(stack); } + +/* + * This slab initializes integers to zero, so use "-1" for "tip is best" and + * "i + 1" for "bases[i] is best". + */ +define_commit_slab(best_branch_base, int); +static struct best_branch_base best_branch_base; +#define get_best(c) (*best_branch_base_at(&best_branch_base, (c))) +#define set_best(c,v) (*best_branch_base_at(&best_branch_base, (c)) = (v)) + +int get_branch_base_for_tip(struct repository *r, + struct commit *tip, + struct commit **bases, + size_t bases_nr) +{ + int best_index = -1; + struct commit *branch_point = NULL; + struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; + int found_missing_gen = 0; + + if (!bases_nr) + return -1; + + repo_parse_commit(r, tip); + if (commit_graph_generation(tip) == GENERATION_NUMBER_INFINITY) + found_missing_gen = 1; + + /* Check for missing generation numbers. */ + for (size_t i = 0; i < bases_nr; i++) { + struct commit *c = bases[i]; + repo_parse_commit(r, c); + if (commit_graph_generation(c) == GENERATION_NUMBER_INFINITY) + found_missing_gen = 1; + } + + if (found_missing_gen) { + struct commit **commits; + size_t commits_nr = bases_nr + 1; + + CALLOC_ARRAY(commits, commits_nr); + COPY_ARRAY(commits, bases, bases_nr); + commits[bases_nr] = tip; + ensure_generations_valid(r, commits, commits_nr); + free(commits); + } + + /* Initialize queue and slab now that generations are guaranteed. */ + init_best_branch_base(&best_branch_base); + set_best(tip, -1); + prio_queue_put(&queue, tip); + + for (size_t i = 0; i < bases_nr; i++) { + struct commit *c = bases[i]; + int best = get_best(c); + + /* Has this already been marked as best by another commit? */ + if (best) { + if (best == -1) { + /* We agree at this position. Stop now. */ + best_index = i + 1; + goto cleanup; + } + continue; + } + + set_best(c, i + 1); + prio_queue_put(&queue, c); + } + + while (queue.nr) { + struct commit *c = prio_queue_get(&queue); + int best_for_c = get_best(c); + int best_for_p, positive; + struct commit *parent; + + /* Have we reached a known branch point? It's optimal. */ + if (c == branch_point) + break; + + repo_parse_commit(r, c); + if (!c->parents) + continue; + + parent = c->parents->item; + repo_parse_commit(r, parent); + best_for_p = get_best(parent); + + if (!best_for_p) { + /* 'parent' is new, so pass along best_for_c. */ + set_best(parent, best_for_c); + prio_queue_put(&queue, parent); + continue; + } + + if (best_for_p > 0 && best_for_c > 0) { + /* Collision among bases. Minimize. */ + if (best_for_c < best_for_p) + set_best(parent, best_for_c); + continue; + } + + /* + * At this point, we have reached a commit that is reachable + * from the tip, either from 'c' or from an earlier commit to + * have 'parent' as its first parent. + * + * Update 'best_index' to match the minimum of all base indices + * to reach 'parent'. + */ + + /* Exactly one is positive due to initial conditions. */ + positive = (best_for_c < 0) ? best_for_p : best_for_c; + + if (best_index < 0 || positive < best_index) + best_index = positive; + + /* No matter what, track that the parent is reachable from tip. */ + set_best(parent, -1); + branch_point = parent; + } + +cleanup: + clear_best_branch_base(&best_branch_base); + clear_prio_queue(&queue); + return best_index > 0 ? best_index - 1 : -1; +} diff --git a/commit-reach.h b/commit-reach.h index bf63cc468f..9a745b7e17 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -139,4 +139,21 @@ void tips_reachable_from_bases(struct repository *r, struct commit **tips, size_t tips_nr, int mark); +/* + * Given a 'tip' commit and a list potential 'bases', return the index 'i' that + * minimizes the number of commits in the first-parent history of 'tip' and not + * in the first-parent history of 'bases[i]'. + * + * Among a list of long-lived branches that are updated only by merges (with the + * first parent being the previous position of the branch), this would inform + * which branch was used to create the tip reference. + * + * Returns -1 if no common point is found in first-parent histories, which is + * rare, but possible with multiple root commits. + */ +int get_branch_base_for_tip(struct repository *r, + struct commit *tip, + struct commit **bases, + size_t bases_nr); + #endif @@ -85,12 +85,18 @@ struct commit *lookup_commit(struct repository *r, const struct object_id *oid) struct commit *lookup_commit_reference_by_name(const char *name) { + return lookup_commit_reference_by_name_gently(name, 0); +} + +struct commit *lookup_commit_reference_by_name_gently(const char *name, + int quiet) +{ struct object_id oid; struct commit *commit; if (repo_get_oid_committish(the_repository, name, &oid)) return NULL; - commit = lookup_commit_reference(the_repository, &oid); + commit = lookup_commit_reference_gently(the_repository, &oid, quiet); if (repo_parse_commit(the_repository, commit)) return NULL; return commit; @@ -177,7 +183,7 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid) commit_graft_oid_access); } -static void unparse_commit(struct repository *r, const struct object_id *oid) +void unparse_commit(struct repository *r, const struct object_id *oid) { struct commit *c = lookup_commit(r, oid); @@ -270,7 +276,7 @@ static int read_graft_file(struct repository *r, const char *graft_file) "to convert the grafts into replace refs.\n" "\n" "Turn this message off by running\n" - "\"git config advice.graftFileDeprecated false\"")); + "\"git config set advice.graftFileDeprecated false\"")); while (!strbuf_getwholeline(&buf, fp, '\n')) { /* The format is just "Commit Parent1 Parent2 ...\n" */ struct commit_graft *graft = read_graft_line(&buf); @@ -286,14 +292,14 @@ static int read_graft_file(struct repository *r, const char *graft_file) void prepare_commit_graft(struct repository *r) { - char *graft_file; + const char *graft_file; if (r->parsed_objects->commit_graft_prepared) return; if (!startup_info->have_repository) return; - graft_file = get_graft_file(r); + graft_file = repo_get_graft_file(r); read_graft_file(r, graft_file); /* make sure shallows are read */ is_repository_shallow(r); @@ -318,18 +324,6 @@ int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data) return ret; } -void reset_commit_grafts(struct repository *r) -{ - int i; - - for (i = 0; i < r->parsed_objects->grafts_nr; i++) { - unparse_commit(r, &r->parsed_objects->grafts[i]->oid); - free(r->parsed_objects->grafts[i]); - } - r->parsed_objects->grafts_nr = 0; - r->parsed_objects->commit_graft_prepared = 0; -} - struct commit_buffer { void *buffer; unsigned long size; @@ -601,7 +595,8 @@ int repo_parse_commit_internal(struct repository *r, } ret = parse_commit_buffer(r, item, buffer, size, 0); - if (save_commit_buffer && !ret) { + if (save_commit_buffer && !ret && + !get_cached_commit_buffer(r, item, NULL)) { set_commit_buffer(r, item, buffer, size); return 0; } @@ -1150,11 +1145,14 @@ int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct gi static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid) { + char *keyid_to_free = NULL; + int ret = 0; if (!keyid || !*keyid) - keyid = get_signing_key(); + keyid = keyid_to_free = get_signing_key(); if (sign_buffer(buf, sig, keyid)) - return -1; - return 0; + ret = -1; + free(keyid_to_free); + return ret; } int parse_signed_commit(const struct commit *commit, @@ -1960,5 +1958,5 @@ int run_commit_hook(int editor_is_used, const char *index_file, va_end(args); opt.invoked_hook = invoked_hook; - return run_hooks_opt(name, &opt); + return run_hooks_opt(the_repository, name, &opt); } @@ -81,6 +81,8 @@ struct commit *lookup_commit_reference_gently(struct repository *r, const struct object_id *oid, int quiet); struct commit *lookup_commit_reference_by_name(const char *name); +struct commit *lookup_commit_reference_by_name_gently(const char *name, + int quiet); /* * Look up object named by "oid", dereference tag as necessary, @@ -108,6 +110,8 @@ static inline int repo_parse_commit_no_graph(struct repository *r, void parse_commit_or_die(struct commit *item); +void unparse_commit(struct repository *r, const struct object_id *oid); + struct buffer_slab; struct buffer_slab *allocate_commit_buffer_slab(void); void free_commit_buffer_slab(struct buffer_slab *bs); @@ -240,7 +244,6 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid); int register_commit_graft(struct repository *r, struct commit_graft *, int); void prepare_commit_graft(struct repository *r); struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid); -void reset_commit_grafts(struct repository *r); struct commit *get_fork_point(const char *refname, struct commit *commit); @@ -251,7 +254,10 @@ struct oid_array; struct ref; int for_each_commit_graft(each_commit_graft_fn, void *); -int interactive_add(const char **argv, const char *prefix, int patch); +int interactive_add(struct repository *repo, + const char **argv, + const char *prefix, + int patch); struct commit_extra_header { struct commit_extra_header *next; diff --git a/compat/compiler.h b/compat/compiler.h index e9ad9db84f..e12e426404 100644 --- a/compat/compiler.h +++ b/compat/compiler.h @@ -9,7 +9,7 @@ static inline void get_compiler_info(struct strbuf *info) { - int len = info->len; + size_t len = info->len; #ifdef __clang__ strbuf_addf(info, "clang: %s\n", __clang_version__); #elif defined(__GNUC__) @@ -27,7 +27,7 @@ static inline void get_compiler_info(struct strbuf *info) static inline void get_libc_info(struct strbuf *info) { - int len = info->len; + size_t len = info->len; #ifdef __GLIBC__ strbuf_addf(info, "glibc: %s\n", gnu_get_libc_version()); diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c index 52f4f29720..fe149a1b37 100644 --- a/compat/fsmonitor/fsm-ipc-darwin.c +++ b/compat/fsmonitor/fsm-ipc-darwin.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "gettext.h" diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c index 2fc67442eb..dfa551459d 100644 --- a/compat/fsmonitor/fsm-listen-darwin.c +++ b/compat/fsmonitor/fsm-listen-darwin.c @@ -516,6 +516,12 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state) } data->stream_started = 1; + /* + * Our fs event listener is now running, so it's safe to start + * serving client requests. + */ + ipc_server_start_async(state->ipc_server_data); + pthread_mutex_lock(&data->dq_lock); pthread_cond_wait(&data->dq_finished, &data->dq_lock); pthread_mutex_unlock(&data->dq_lock); diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c index 5a21dade7b..9a6efc9bea 100644 --- a/compat/fsmonitor/fsm-listen-win32.c +++ b/compat/fsmonitor/fsm-listen-win32.c @@ -431,9 +431,9 @@ static int recv_rdcw_watch(struct one_watch *watch) * but I observed ERROR_ACCESS_DENIED (0x05) errors during * testing. * - * Note that we only get notificaiton events for events + * Note that we only get notification events for events * *within* the directory, not *on* the directory itself. - * (These might be properies of the parent directory, for + * (These might be properties of the parent directory, for * example). * * NEEDSWORK: We might try to check for the deleted directory @@ -741,6 +741,12 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state) start_rdcw_watch(data->watch_gitdir) == -1) goto force_error_stop; + /* + * Now that we've established the rdcw watches, we can start + * serving clients. + */ + ipc_server_start_async(state->ipc_server_data); + for (;;) { dwWait = WaitForMultipleObjects(data->nr_listener_handles, data->hListener, diff --git a/compat/mingw.c b/compat/mingw.c index 29d3f09768..63f36c893b 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "../git-compat-util.h" #include "win32.h" #include <aclapi.h> @@ -243,7 +245,8 @@ static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; static char *unset_environment_variables; int mingw_core_config(const char *var, const char *value, - const struct config_context *ctx, void *cb) + const struct config_context *ctx UNUSED, + void *cb UNUSED) { if (!strcmp(var, "core.hidedotfiles")) { if (value && !strcasecmp(value, "dotgitonly")) @@ -453,7 +456,7 @@ static int set_hidden_flag(const wchar_t *path, int set) return -1; } -int mingw_mkdir(const char *path, int mode) +int mingw_mkdir(const char *path, int mode UNUSED) { int ret; wchar_t wpath[MAX_PATH]; @@ -499,7 +502,7 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) * to append to the file. */ handle = CreateFileW(wfilename, FILE_APPEND_DATA, - FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); @@ -530,6 +533,70 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) } /* + * Ideally, we'd use `_wopen()` to implement this functionality so that we + * don't have to reimplement it, but unfortunately we do not have tight control + * over the share mode there. And while `_wsopen()` and friends exist that give + * us _some_ control over the share mode, this family of functions doesn't give + * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict + * requirement for us though so that we can unlink or rename over files that + * are held open by another process. + * + * We are thus forced to implement our own emulation of `open()`. To make our + * life simpler we only implement basic support for this, namely opening + * existing files for reading and/or writing. This means that newly created + * files won't have their sharing mode set up correctly, but for now I couldn't + * find any case where this matters. We may have to revisit that in the future + * though based on our needs. + */ +static int mingw_open_existing(const wchar_t *filename, int oflags, ...) +{ + SECURITY_ATTRIBUTES security_attributes = { + .nLength = sizeof(security_attributes), + .bInheritHandle = !(oflags & O_NOINHERIT), + }; + HANDLE handle; + DWORD access; + int fd; + + /* We only support basic flags. */ + if (oflags & ~(O_ACCMODE | O_NOINHERIT)) { + errno = ENOSYS; + return -1; + } + + switch (oflags & O_ACCMODE) { + case O_RDWR: + access = GENERIC_READ | GENERIC_WRITE; + break; + case O_WRONLY: + access = GENERIC_WRITE; + break; + default: + access = GENERIC_READ; + break; + } + + handle = CreateFileW(filename, access, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); + + /* See `mingw_open_append()` for why we have this conversion. */ + if (err == ERROR_INVALID_PARAMETER) + err = ERROR_PATH_NOT_FOUND; + + errno = err_win_to_posix(err); + return -1; + } + + fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY); + if (fd < 0) + CloseHandle(handle); + return fd; +} + +/* * Does the pathname map to the local named pipe filesystem? * That is, does it have a "//./pipe/" prefix? */ @@ -564,6 +631,8 @@ int mingw_open (const char *filename, int oflags, ...) if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename)) open_fn = mingw_open_append; + else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT))) + open_fn = mingw_open_existing; else open_fn = _wopen; @@ -597,7 +666,7 @@ int mingw_open (const char *filename, int oflags, ...) return fd; } -static BOOL WINAPI ctrl_ignore(DWORD type) +static BOOL WINAPI ctrl_ignore(DWORD type UNUSED) { return TRUE; } @@ -779,7 +848,7 @@ static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts) */ static int has_valid_directory_prefix(wchar_t *wfilename) { - int n = wcslen(wfilename); + size_t n = wcslen(wfilename); while (n > 0) { wchar_t c = wfilename[--n]; @@ -888,7 +957,7 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf) */ static int do_stat_internal(int follow, const char *file_name, struct stat *buf) { - int namelen; + size_t namelen; char alt_name[PATH_MAX]; if (!do_lstat(follow, file_name, buf)) @@ -1003,7 +1072,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times) osfilehandle = CreateFileW(wfilename, FILE_WRITE_ATTRIBUTES, - 0 /*FileShare.None*/, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, (attrs != INVALID_FILE_ATTRIBUTES && @@ -1085,7 +1154,7 @@ int mkstemp(char *template) return git_mkstemp_mode(template, 0600); } -int gettimeofday(struct timeval *tv, void *tz) +int gettimeofday(struct timeval *tv, void *tz UNUSED) { FILETIME ft; long long hnsec; @@ -1271,7 +1340,8 @@ static const char *parse_interpreter(const char *cmd) { static char buf[100]; char *p, *opt; - int n, fd; + ssize_t n; /* read() can return negative values */ + int fd; /* don't even try a .exe */ n = strlen(cmd); @@ -1336,7 +1406,7 @@ static char *path_lookup(const char *cmd, int exe_only) { const char *path; char *prog = NULL; - int len = strlen(cmd); + size_t len = strlen(cmd); int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe"); if (strpbrk(cmd, "/\\")) @@ -1953,7 +2023,7 @@ char *mingw_getenv(const char *name) #define GETENV_MAX_RETAIN 64 static char *values[GETENV_MAX_RETAIN]; static int value_counter; - int len_key, len_value; + size_t len_key, len_value; wchar_t *w_key; char *value; wchar_t w_value[32768]; @@ -1965,7 +2035,8 @@ char *mingw_getenv(const char *name) /* We cannot use xcalloc() here because that uses getenv() itself */ w_key = calloc(len_key, sizeof(wchar_t)); if (!w_key) - die("Out of memory, (tried to allocate %u wchar_t's)", len_key); + die("Out of memory, (tried to allocate %"PRIuMAX" wchar_t's)", + (uintmax_t)len_key); xutftowcs(w_key, name, len_key); /* GetEnvironmentVariableW() only sets the last error upon failure */ SetLastError(ERROR_SUCCESS); @@ -1980,7 +2051,8 @@ char *mingw_getenv(const char *name) /* We cannot use xcalloc() here because that uses getenv() itself */ value = calloc(len_value, sizeof(char)); if (!value) - die("Out of memory, (tried to allocate %u bytes)", len_value); + die("Out of memory, (tried to allocate %"PRIuMAX" bytes)", + (uintmax_t)len_value); xwcstoutf(value, w_value, len_value); /* @@ -1998,7 +2070,7 @@ char *mingw_getenv(const char *name) int mingw_putenv(const char *namevalue) { - int size; + size_t size; wchar_t *wide, *equal; BOOL result; @@ -2008,7 +2080,8 @@ int mingw_putenv(const char *namevalue) size = strlen(namevalue) * 2 + 1; wide = calloc(size, sizeof(wchar_t)); if (!wide) - die("Out of memory, (tried to allocate %u wchar_t's)", size); + die("Out of memory, (tried to allocate %" PRIuMAX " wchar_t's)", + (uintmax_t)size); xutftowcs(wide, namevalue, size); equal = wcschr(wide, L'='); if (!equal) @@ -2148,10 +2221,16 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz) #undef rename int mingw_rename(const char *pold, const char *pnew) { + static int supports_file_rename_info_ex = 1; DWORD attrs, gle; int tries = 0; wchar_t wpold[MAX_PATH], wpnew[MAX_PATH]; - if (xutftowcs_path(wpold, pold) < 0 || xutftowcs_path(wpnew, pnew) < 0) + int wpnew_len; + + if (xutftowcs_path(wpold, pold) < 0) + return -1; + wpnew_len = xutftowcs_path(wpnew, pnew); + if (wpnew_len < 0) return -1; /* @@ -2162,11 +2241,84 @@ int mingw_rename(const char *pold, const char *pnew) return 0; if (errno != EEXIST) return -1; + repeat: - if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING)) - return 0; + if (supports_file_rename_info_ex) { + /* + * Our minimum required Windows version is still set to Windows + * Vista. We thus have to declare required infrastructure for + * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to + * 0x0A00. Furthermore, we have to handle cases where the + * FileRenameInfoEx call isn't supported yet. + */ +#define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001 +#define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002 + FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22; + struct { + /* + * This is usually an unnamed union, but that is not + * part of ISO C99. We thus inline the field, as we + * really only care for the Flags field anyway. + */ + DWORD Flags; + HANDLE RootDirectory; + DWORD FileNameLength; + /* + * The actual structure is defined with a single-character + * flex array so that the structure has to be allocated on + * the heap. As we declare this structure ourselves though + * we can avoid the allocation and define FileName to have + * MAX_PATH bytes. + */ + WCHAR FileName[MAX_PATH]; + } rename_info = { 0 }; + HANDLE old_handle = INVALID_HANDLE_VALUE; + BOOL success; + + old_handle = CreateFileW(wpold, DELETE, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (old_handle == INVALID_HANDLE_VALUE) { + errno = err_win_to_posix(GetLastError()); + return -1; + } + + rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS | + FILE_RENAME_FLAG_POSIX_SEMANTICS; + rename_info.FileNameLength = wpnew_len * sizeof(WCHAR); + memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR)); + + success = SetFileInformationByHandle(old_handle, FileRenameInfoEx, + &rename_info, sizeof(rename_info)); + gle = GetLastError(); + CloseHandle(old_handle); + if (success) + return 0; + + /* + * When we see ERROR_INVALID_PARAMETER we can assume that the + * current system doesn't support FileRenameInfoEx. Keep us + * from using it in future calls and retry. + */ + if (gle == ERROR_INVALID_PARAMETER) { + supports_file_rename_info_ex = 0; + goto repeat; + } + + /* + * In theory, we shouldn't get ERROR_ACCESS_DENIED because we + * always open files with FILE_SHARE_DELETE But in practice we + * cannot assume that Git is the only one accessing files, and + * other applications may not set FILE_SHARE_DELETE. So we have + * to retry. + */ + } else { + if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING)) + return 0; + gle = GetLastError(); + } + /* TODO: translate more errors */ - gle = GetLastError(); if (gle == ERROR_ACCESS_DENIED && (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { @@ -2252,7 +2404,7 @@ char *mingw_query_user_email(void) return get_extended_user_info(NameUserPrincipal); } -struct passwd *getpwuid(int uid) +struct passwd *getpwuid(int uid UNUSED) { static unsigned initialized; static char user_name[100]; @@ -2304,7 +2456,7 @@ static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL; * length to call the signal handler. */ -static unsigned __stdcall ticktack(void *dummy) +static unsigned __stdcall ticktack(void *dummy UNUSED) { while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) { mingw_raise(SIGALRM); @@ -2352,7 +2504,7 @@ static inline int is_timeval_eq(const struct timeval *i1, const struct timeval * return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec; } -int setitimer(int type, struct itimerval *in, struct itimerval *out) +int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out) { static const struct timeval zero; static int atexit_done; @@ -3082,7 +3234,8 @@ static void maybe_redirect_std_handles(void) */ int wmain(int argc, const wchar_t **wargv) { - int i, maxlen, exit_status; + int i, exit_status; + size_t maxlen; char *buffer, **save; const char **argv; diff --git a/compat/mingw.h b/compat/mingw.h index 27b61284f4..ebfb8ba423 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -122,17 +122,17 @@ struct utsname { * trivial stubs */ -static inline int readlink(const char *path, char *buf, size_t bufsiz) +static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED) { errno = ENOSYS; return -1; } -static inline int symlink(const char *oldpath, const char *newpath) +static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED) { errno = ENOSYS; return -1; } -static inline int fchmod(int fildes, mode_t mode) +static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED) { errno = ENOSYS; return -1; } #ifndef __MINGW64_VERSION_MAJOR static inline pid_t fork(void) { errno = ENOSYS; return -1; } #endif -static inline unsigned int alarm(unsigned int seconds) +static inline unsigned int alarm(unsigned int seconds UNUSED) { return 0; } static inline int fsync(int fd) { return _commit(fd); } @@ -140,9 +140,9 @@ static inline void sync(void) {} static inline uid_t getuid(void) { return 1; } -static inline struct passwd *getpwnam(const char *name) +static inline struct passwd *getpwnam(const char *name UNUSED) { return NULL; } -static inline int fcntl(int fd, int cmd, ...) +static inline int fcntl(int fd UNUSED, int cmd, ...) { if (cmd == F_GETFD || cmd == F_SETFD) return 0; @@ -151,17 +151,17 @@ static inline int fcntl(int fd, int cmd, ...) } #define sigemptyset(x) (void)0 -static inline int sigaddset(sigset_t *set, int signum) +static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED) { return 0; } #define SIG_BLOCK 0 #define SIG_UNBLOCK 0 -static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED) { return 0; } static inline pid_t getppid(void) { return 1; } static inline pid_t getpgid(pid_t pid) { return pid == 0 ? getpid() : pid; } -static inline pid_t tcgetpgrp(int fd) +static inline pid_t tcgetpgrp(int fd UNUSED) { return getpid(); } /* diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c index 2c0ace7075..145255da43 100644 --- a/compat/nedmalloc/nedmalloc.c +++ b/compat/nedmalloc/nedmalloc.c @@ -31,6 +31,8 @@ DEALINGS IN THE SOFTWARE. /*#pragma optimize("a", on)*/ #endif +#pragma GCC diagnostic ignored "-Wunused-parameter" + /*#define FULLSANITYCHECKS*/ #include "nedmalloc.h" diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index 0bd5c24250..f7cc7b3be5 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -4,6 +4,7 @@ */ #define PRECOMPOSE_UNICODE_C +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "config.h" diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c index 6c5d455e92..8d93a9b93f 100644 --- a/compat/regex/regcomp.c +++ b/compat/regex/regcomp.c @@ -17,6 +17,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#pragma GCC diagnostic ignored "-Wunused-parameter" + #if defined __TANDEM /* This is currently duplicated from git-compat-utils.h */ # ifdef NO_INTPTR_T diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c index e92be5741d..2eeec82f40 100644 --- a/compat/regex/regexec.c +++ b/compat/regex/regexec.c @@ -292,7 +292,7 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); concerned. If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stroed in REGS. (For the "_2" variants, the offsets are + and all groups are stored in REGS. (For the "_2" variants, the offsets are computed relative to the concatenation, not relative to the individual strings.) diff --git a/compat/simple-ipc/ipc-shared.c b/compat/simple-ipc/ipc-shared.c index cb176d966f..d1c21b49bd 100644 --- a/compat/simple-ipc/ipc-shared.c +++ b/compat/simple-ipc/ipc-shared.c @@ -16,11 +16,12 @@ int ipc_server_run(const char *path, const struct ipc_server_opts *opts, struct ipc_server_data *server_data = NULL; int ret; - ret = ipc_server_run_async(&server_data, path, opts, - application_cb, application_data); + ret = ipc_server_init_async(&server_data, path, opts, + application_cb, application_data); if (ret) return ret; + ipc_server_start_async(server_data); ret = ipc_server_await(server_data); ipc_server_free(server_data); diff --git a/compat/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c index 9b3f2cdf8c..7db3b2a897 100644 --- a/compat/simple-ipc/ipc-unix-socket.c +++ b/compat/simple-ipc/ipc-unix-socket.c @@ -328,6 +328,7 @@ struct ipc_server_data { int back_pos; int front_pos; + int started; int shutdown_requested; int is_stopped; }; @@ -712,7 +713,7 @@ static int accept_thread__wait_for_connection( * Block SIGPIPE in this thread for the life of the thread. This * avoids any stray SIGPIPE signals when closing pipe fds under * extremely heavy loads (such as when the fifo queue is full and we - * drop incomming connections). + * drop incoming connections). */ static void *accept_thread_proc(void *_accept_thread_data) { @@ -824,10 +825,10 @@ static int setup_listener_socket( /* * Start IPC server in a pool of background threads. */ -int ipc_server_run_async(struct ipc_server_data **returned_server_data, - const char *path, const struct ipc_server_opts *opts, - ipc_server_application_cb *application_cb, - void *application_data) +int ipc_server_init_async(struct ipc_server_data **returned_server_data, + const char *path, const struct ipc_server_opts *opts, + ipc_server_application_cb *application_cb, + void *application_data) { struct unix_ss_socket *server_socket = NULL; struct ipc_server_data *server_data; @@ -888,6 +889,12 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, server_data->accept_thread->fd_send_shutdown = sv[0]; server_data->accept_thread->fd_wait_shutdown = sv[1]; + /* + * Hold work-available mutex so that no work can start until + * we unlock it. + */ + pthread_mutex_lock(&server_data->work_available_mutex); + if (pthread_create(&server_data->accept_thread->pthread_id, NULL, accept_thread_proc, server_data->accept_thread)) die_errno(_("could not start accept_thread '%s'"), path); @@ -918,6 +925,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, return 0; } +void ipc_server_start_async(struct ipc_server_data *server_data) +{ + if (!server_data || server_data->started) + return; + + server_data->started = 1; + pthread_mutex_unlock(&server_data->work_available_mutex); +} + /* * Gently tell the IPC server treads to shutdown. * Can be run on any thread. @@ -933,7 +949,9 @@ int ipc_server_stop_async(struct ipc_server_data *server_data) trace2_region_enter("ipc-server", "server-stop-async", NULL); - pthread_mutex_lock(&server_data->work_available_mutex); + /* If we haven't started yet, we are already holding lock. */ + if (server_data->started) + pthread_mutex_lock(&server_data->work_available_mutex); server_data->shutdown_requested = 1; diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c index 8bfe51248e..a8fc812adf 100644 --- a/compat/simple-ipc/ipc-win32.c +++ b/compat/simple-ipc/ipc-win32.c @@ -371,6 +371,9 @@ struct ipc_server_data { HANDLE hEventStopRequested; struct ipc_server_thread_data *thread_list; int is_stopped; + + pthread_mutex_t startup_barrier; + int started; }; enum connect_result { @@ -526,6 +529,16 @@ static int use_connection(struct ipc_server_thread_data *server_thread_data) return ret; } +static void wait_for_startup_barrier(struct ipc_server_data *server_data) +{ + /* + * Temporarily hold the startup_barrier mutex before starting, + * which lets us know that it's OK to start serving requests. + */ + pthread_mutex_lock(&server_data->startup_barrier); + pthread_mutex_unlock(&server_data->startup_barrier); +} + /* * Thread proc for an IPC server worker thread. It handles a series of * connections from clients. It cleans and reuses the hPipe between each @@ -550,6 +563,8 @@ static void *server_thread_proc(void *_server_thread_data) memset(&oConnect, 0, sizeof(oConnect)); oConnect.hEvent = hEventConnected; + wait_for_startup_barrier(server_thread_data->server_data); + for (;;) { cr = wait_for_connection(server_thread_data, &oConnect); @@ -752,10 +767,10 @@ static HANDLE create_new_pipe(wchar_t *wpath, int is_first) return hPipe; } -int ipc_server_run_async(struct ipc_server_data **returned_server_data, - const char *path, const struct ipc_server_opts *opts, - ipc_server_application_cb *application_cb, - void *application_data) +int ipc_server_init_async(struct ipc_server_data **returned_server_data, + const char *path, const struct ipc_server_opts *opts, + ipc_server_application_cb *application_cb, + void *application_data) { struct ipc_server_data *server_data; wchar_t wpath[MAX_PATH]; @@ -787,6 +802,13 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, strbuf_addstr(&server_data->buf_path, path); wcscpy(server_data->wpath, wpath); + /* + * Hold the startup_barrier lock so that no threads will progress + * until ipc_server_start_async() is called. + */ + pthread_mutex_init(&server_data->startup_barrier, NULL); + pthread_mutex_lock(&server_data->startup_barrier); + if (nr_threads < 1) nr_threads = 1; @@ -837,6 +859,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, return 0; } +void ipc_server_start_async(struct ipc_server_data *server_data) +{ + if (!server_data || server_data->started) + return; + + server_data->started = 1; + pthread_mutex_unlock(&server_data->startup_barrier); +} + int ipc_server_stop_async(struct ipc_server_data *server_data) { if (!server_data) @@ -850,6 +881,13 @@ int ipc_server_stop_async(struct ipc_server_data *server_data) * We DO NOT attempt to force them to drop an active connection. */ SetEvent(server_data->hEventStopRequested); + + /* + * If we haven't yet told the threads they are allowed to run, + * do so now, so they can receive the shutdown event. + */ + ipc_server_start_async(server_data); + return 0; } @@ -900,5 +938,7 @@ void ipc_server_free(struct ipc_server_data *server_data) free(std); } + pthread_mutex_destroy(&server_data->startup_barrier); + free(server_data); } diff --git a/compat/stub/procinfo.c b/compat/stub/procinfo.c index 12c0a23c9e..3168cd5714 100644 --- a/compat/stub/procinfo.c +++ b/compat/stub/procinfo.c @@ -6,6 +6,6 @@ * Stub. See sample implementations in compat/linux/procinfo.c and * compat/win32/trace2_win32_process_info.c. */ -void trace2_collect_process_info(enum trace2_process_info_reason reason) +void trace2_collect_process_info(enum trace2_process_info_reason reason UNUSED) { } diff --git a/compat/terminal.c b/compat/terminal.c index 0afda730f2..d54efa1c5d 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -594,7 +594,7 @@ void restore_term(void) { } -char *git_terminal_prompt(const char *prompt, int echo) +char *git_terminal_prompt(const char *prompt, int echo UNUSED) { return getpass(prompt); } diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h index 3a959d124c..a261a925b7 100644 --- a/compat/vcbuild/include/unistd.h +++ b/compat/vcbuild/include/unistd.h @@ -14,7 +14,11 @@ typedef _mode_t mode_t; #ifndef _SSIZE_T_ #define _SSIZE_T_ +#ifdef _WIN64 +typedef __int64 _ssize_t; +#else typedef long _ssize_t; +#endif /* _WIN64 */ #ifndef _OFF_T_ #define _OFF_T_ diff --git a/compat/win32/headless.c b/compat/win32/headless.c index 8b00dfe3bd..11392a0b9a 100644 --- a/compat/win32/headless.c +++ b/compat/win32/headless.c @@ -11,6 +11,8 @@ #include <stdlib.h> #include <wchar.h> +#pragma GCC diagnostic ignored "-Wunused-parameter" + /* * If `dir` contains the path to a Git exec directory, extend `PATH` to * include the corresponding `bin/` directory (which is where all those diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c index b658ca3f81..966ef779b9 100644 --- a/compat/win32/path-utils.c +++ b/compat/win32/path-utils.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "../../git-compat-util.h" #include "../../environment.h" diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c index 85f8f7920c..58980a529c 100644 --- a/compat/win32/pthread.c +++ b/compat/win32/pthread.c @@ -21,7 +21,7 @@ static unsigned __stdcall win32_start_routine(void *arg) return 0; } -int pthread_create(pthread_t *thread, const void *unused, +int pthread_create(pthread_t *thread, const void *attr UNUSED, void *(*start_routine)(void *), void *arg) { thread->arg = arg; diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index cc3221cb2c..e2b5c4f64c 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -18,7 +18,7 @@ */ #define pthread_mutex_t CRITICAL_SECTION -static inline int return_0(int i) { +static inline int return_0(int i UNUSED) { return 0; } #define pthread_mutex_init(a,b) return_0((InitializeCriticalSection((a)), 0)) @@ -70,7 +70,7 @@ static inline void NORETURN pthread_exit(void *ret) } typedef DWORD pthread_key_t; -static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value)) +static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value) UNUSED) { return (*keyp = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0; } diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c index 0af18d8882..4e4794743a 100644 --- a/compat/win32/syslog.c +++ b/compat/win32/syslog.c @@ -2,7 +2,7 @@ static HANDLE ms_eventlog; -void openlog(const char *ident, int logopt, int facility) +void openlog(const char *ident, int logopt UNUSED, int facility UNUSED) { if (ms_eventlog) return; diff --git a/compat/win32mmap.c b/compat/win32mmap.c index 519d51f2b6..a4ab4cb939 100644 --- a/compat/win32mmap.c +++ b/compat/win32mmap.c @@ -40,7 +40,7 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of return MAP_FAILED; } -int git_munmap(void *start, size_t length) +int git_munmap(void *start, size_t length UNUSED) { return !UnmapViewOfFile(start); } diff --git a/compat/winansi.c b/compat/winansi.c index 575813bde8..1b3f916b9f 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -340,7 +340,7 @@ enum { TEXT = 0, ESCAPE = 033, BRACKET = '[' }; -static DWORD WINAPI console_thread(LPVOID unused) +static DWORD WINAPI console_thread(LPVOID data UNUSED) { unsigned char buffer[BUFFER_SIZE]; DWORD bytes; @@ -300,18 +300,22 @@ done: return ret; } -static int include_by_branch(const char *cond, size_t cond_len) +static int include_by_branch(struct config_include_data *data, + const char *cond, size_t cond_len) { int flags; int ret; struct strbuf pattern = STRBUF_INIT; - const char *refname = !the_repository->gitdir ? - NULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository), - "HEAD", 0, NULL, &flags); - const char *shortname; + const char *refname, *shortname; - if (!refname || !(flags & REF_ISSYMREF) || - !skip_prefix(refname, "refs/heads/", &shortname)) + if (!data->repo || data->repo->ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + return 0; + + refname = refs_resolve_ref_unsafe(get_main_ref_store(data->repo), + "HEAD", 0, NULL, &flags); + if (!refname || + !(flags & REF_ISSYMREF) || + !skip_prefix(refname, "refs/heads/", &shortname)) return 0; strbuf_add(&pattern, cond, cond_len); @@ -406,7 +410,7 @@ static int include_condition_is_true(const struct key_value_info *kvi, else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len)) return include_by_gitdir(kvi, opts, cond, cond_len, 1); else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len)) - return include_by_branch(cond, cond_len); + return include_by_branch(inc, cond, cond_len); else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond, &cond_len)) return include_by_remote_url(inc, cond, cond_len); @@ -1446,26 +1450,6 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.prefersymlinkrefs")) { - prefer_symlink_refs = git_config_bool(var, value); - return 0; - } - - if (!strcmp(var, "core.logallrefupdates")) { - if (value && !strcasecmp(value, "always")) - log_all_ref_updates = LOG_REFS_ALWAYS; - else if (git_config_bool(var, value)) - log_all_ref_updates = LOG_REFS_NORMAL; - else - log_all_ref_updates = LOG_REFS_NONE; - return 0; - } - - if (!strcmp(var, "core.warnambiguousrefs")) { - warn_ambiguous_refs = git_config_bool(var, value); - return 0; - } - if (!strcmp(var, "core.abbrev")) { if (!value) return config_error_nonbool(var); @@ -1509,33 +1493,11 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.packedgitwindowsize")) { - int pgsz_x2 = getpagesize() * 2; - packed_git_window_size = git_config_ulong(var, value, ctx->kvi); - - /* This value must be multiple of (pagesize * 2) */ - packed_git_window_size /= pgsz_x2; - if (packed_git_window_size < 1) - packed_git_window_size = 1; - packed_git_window_size *= pgsz_x2; - return 0; - } - if (!strcmp(var, "core.bigfilethreshold")) { big_file_threshold = git_config_ulong(var, value, ctx->kvi); return 0; } - if (!strcmp(var, "core.packedgitlimit")) { - packed_git_limit = git_config_ulong(var, value, ctx->kvi); - return 0; - } - - if (!strcmp(var, "core.deltabasecachelimit")) { - delta_base_cache_limit = git_config_ulong(var, value, ctx->kvi); - return 0; - } - if (!strcmp(var, "core.autocrlf")) { if (value && !strcasecmp(value, "input")) { auto_crlf = AUTO_CRLF_INPUT; @@ -1574,14 +1536,6 @@ static int git_default_core_config(const char *var, const char *value, return git_config_string(&check_roundtrip_encoding, var, value); } - if (!strcmp(var, "core.notesref")) { - if (!value) - return config_error_nonbool(var); - free(notes_ref_name); - notes_ref_name = xstrdup(value); - return 0; - } - if (!strcmp(var, "core.editor")) { FREE_AND_NULL(editor_program); return git_config_string(&editor_program, var, value); @@ -1596,7 +1550,8 @@ static int git_default_core_config(const char *var, const char *value, else if (value[0]) { if (strchr(value, '\n')) return error(_("%s cannot contain newline"), var); - comment_line_str = xstrdup(value); + comment_line_str = value; + FREE_AND_NULL(comment_line_str_to_free); auto_comment_line_char = 0; } else return error(_("%s must have at least one character"), var); @@ -2202,7 +2157,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data) } } -void read_early_config(config_fn_t cb, void *data) +void read_early_config(struct repository *repo, config_fn_t cb, void *data) { struct config_options opts = {0}; struct strbuf commondir = STRBUF_INIT; @@ -2210,9 +2165,9 @@ void read_early_config(config_fn_t cb, void *data) opts.respect_includes = 1; - if (have_git_dir()) { - opts.commondir = get_git_common_dir(); - opts.git_dir = get_git_dir(); + if (repo && repo->gitdir) { + opts.commondir = repo_get_common_dir(repo); + opts.git_dir = repo_get_git_dir(repo); /* * When setup_git_directory() was not yet asked to discover the * GIT_DIR, we ask discover_git_directory() to figure out whether there @@ -2232,10 +2187,6 @@ void read_early_config(config_fn_t cb, void *data) strbuf_release(&gitdir); } -/* - * Read config but only enumerate system and global settings. - * Omit any repo-local, worktree-local, or command-line settings. - */ void read_very_early_config(config_fn_t cb, void *data) { struct config_options opts = { 0 }; @@ -2564,7 +2515,7 @@ static void git_config_check_init(struct repository *repo) repo_read_config(repo); } -static void repo_config_clear(struct repository *repo) +void repo_config_clear(struct repository *repo) { if (!repo->config || !repo->config->hash_initialized) return; @@ -2611,7 +2562,7 @@ int repo_config_get_string(struct repository *repo, git_config_check_init(repo); ret = git_configset_get_string(repo->config, key, dest); if (ret < 0) - git_die_config(key, NULL); + git_die_config(repo, key, NULL); return ret; } @@ -2622,7 +2573,7 @@ int repo_config_get_string_tmp(struct repository *repo, git_config_check_init(repo); ret = git_configset_get_string_tmp(repo->config, key, dest); if (ret < 0) - git_die_config(key, NULL); + git_die_config(repo, key, NULL); return ret; } @@ -2668,7 +2619,7 @@ int repo_config_get_pathname(struct repository *repo, git_config_check_init(repo); ret = git_configset_get_pathname(repo->config, key, dest); if (ret < 0) - git_die_config(key, NULL); + git_die_config(repo, key, NULL); return ret; } @@ -2694,98 +2645,28 @@ void git_protected_config(config_fn_t fn, void *data) configset_iter(&protected_config, fn, data); } -/* Functions used historically to read configuration from 'the_repository' */ -void git_config(config_fn_t fn, void *data) +int repo_config_get_expiry(struct repository *r, const char *key, char **output) { - repo_config(the_repository, fn, data); -} - -void git_config_clear(void) -{ - repo_config_clear(the_repository); -} - -int git_config_get(const char *key) -{ - return repo_config_get(the_repository, key); -} - -int git_config_get_value(const char *key, const char **value) -{ - return repo_config_get_value(the_repository, key, value); -} + int ret = repo_config_get_string(r, key, output); -int git_config_get_value_multi(const char *key, const struct string_list **dest) -{ - return repo_config_get_value_multi(the_repository, key, dest); -} - -int git_config_get_string_multi(const char *key, - const struct string_list **dest) -{ - return repo_config_get_string_multi(the_repository, key, dest); -} - -int git_config_get_string(const char *key, char **dest) -{ - return repo_config_get_string(the_repository, key, dest); -} - -int git_config_get_string_tmp(const char *key, const char **dest) -{ - return repo_config_get_string_tmp(the_repository, key, dest); -} - -int git_config_get_int(const char *key, int *dest) -{ - return repo_config_get_int(the_repository, key, dest); -} - -int git_config_get_ulong(const char *key, unsigned long *dest) -{ - return repo_config_get_ulong(the_repository, key, dest); -} - -int git_config_get_bool(const char *key, int *dest) -{ - return repo_config_get_bool(the_repository, key, dest); -} - -int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest) -{ - return repo_config_get_bool_or_int(the_repository, key, is_bool, dest); -} - -int git_config_get_maybe_bool(const char *key, int *dest) -{ - return repo_config_get_maybe_bool(the_repository, key, dest); -} - -int git_config_get_pathname(const char *key, char **dest) -{ - return repo_config_get_pathname(the_repository, key, dest); -} - -int git_config_get_expiry(const char *key, const char **output) -{ - int ret = git_config_get_string(key, (char **)output); if (ret) return ret; if (strcmp(*output, "now")) { timestamp_t now = approxidate("now"); if (approxidate(*output) >= now) - git_die_config(key, _("Invalid %s: '%s'"), key, *output); + git_die_config(r, key, _("Invalid %s: '%s'"), key, *output); } return ret; } -int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now) +int repo_config_get_expiry_in_days(struct repository *r, const char *key, + timestamp_t *expiry, timestamp_t now) { const char *expiry_string; intmax_t days; timestamp_t when; - if (git_config_get_string_tmp(key, &expiry_string)) + if (repo_config_get_string_tmp(r, key, &expiry_string)) return 1; /* no such thing */ if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) { @@ -2801,21 +2682,21 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam return -1; /* thing exists but cannot be parsed */ } -int git_config_get_split_index(void) +int repo_config_get_split_index(struct repository *r) { int val; - if (!git_config_get_maybe_bool("core.splitindex", &val)) + if (!repo_config_get_maybe_bool(r, "core.splitindex", &val)) return val; return -1; /* default value */ } -int git_config_get_max_percent_split_change(void) +int repo_config_get_max_percent_split_change(struct repository *r) { int val = -1; - if (!git_config_get_int("splitindex.maxpercentchange", &val)) { + if (!repo_config_get_int(r, "splitindex.maxpercentchange", &val)) { if (0 <= val && val <= 100) return val; @@ -2826,7 +2707,7 @@ int git_config_get_max_percent_split_change(void) return -1; /* default value */ } -int git_config_get_index_threads(int *dest) +int repo_config_get_index_threads(struct repository *r, int *dest) { int is_bool, val; @@ -2836,7 +2717,7 @@ int git_config_get_index_threads(int *dest) return 0; } - if (!git_config_get_bool_or_int("index.threads", &is_bool, &val)) { + if (!repo_config_get_bool_or_int(r, "index.threads", &is_bool, &val)) { if (is_bool) *dest = val ? 0 : 1; else @@ -2857,7 +2738,7 @@ void git_die_config_linenr(const char *key, const char *filename, int linenr) key, filename, linenr); } -void git_die_config(const char *key, const char *err, ...) +void git_die_config(struct repository *r, const char *key, const char *err, ...) { const struct string_list *values; struct key_value_info *kv_info; @@ -2869,7 +2750,7 @@ void git_die_config(const char *key, const char *err, ...) error_fn(err, params); va_end(params); } - if (git_config_get_value_multi(key, &values)) + if (repo_config_get_value_multi(r, key, &values)) BUG("for key '%s' we must have a value to report on", key); kv_info = values->items[values->nr - 1].util; git_die_config_linenr(key, kv_info->filename, kv_info->linenr); @@ -2914,7 +2795,7 @@ static int matches(const char *key, const char *value, { if (strcmp(key, store->key)) return 0; /* not ours */ - if (store->fixed_value) + if (store->fixed_value && value) return !strcmp(store->fixed_value, value); if (!store->value_pattern) return 1; /* always matches */ @@ -3178,21 +3059,21 @@ static void maybe_remove_section(struct config_store_data *store, *end_offset = store->parsed[store->parsed_nr - 1].end; } -int git_config_set_in_file_gently(const char *config_filename, - const char *key, const char *comment, const char *value) +int repo_config_set_in_file_gently(struct repository *r, const char *config_filename, + const char *key, const char *comment, const char *value) { - return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, comment, 0); + return repo_config_set_multivar_in_file_gently(r, config_filename, key, value, NULL, comment, 0); } -void git_config_set_in_file(const char *config_filename, - const char *key, const char *value) +void repo_config_set_in_file(struct repository *r, const char *config_filename, + const char *key, const char *value) { - git_config_set_multivar_in_file(config_filename, key, value, NULL, 0); + repo_config_set_multivar_in_file(r, config_filename, key, value, NULL, 0); } -int git_config_set_gently(const char *key, const char *value) +int repo_config_set_gently(struct repository *r, const char *key, const char *value) { - return git_config_set_multivar_gently(key, value, NULL, 0); + return repo_config_set_multivar_gently(r, key, value, NULL, 0); } int repo_config_set_worktree_gently(struct repository *r, @@ -3201,17 +3082,17 @@ int repo_config_set_worktree_gently(struct repository *r, /* Only use worktree-specific config if it is already enabled. */ if (r->repository_format_worktree_config) { char *file = repo_git_path(r, "config.worktree"); - int ret = git_config_set_multivar_in_file_gently( - file, key, value, NULL, NULL, 0); + int ret = repo_config_set_multivar_in_file_gently( + r, file, key, value, NULL, NULL, 0); free(file); return ret; } return repo_config_set_multivar_gently(r, key, value, NULL, 0); } -void git_config_set(const char *key, const char *value) +void repo_config_set(struct repository *r, const char *key, const char *value) { - git_config_set_multivar(key, value, NULL, 0); + repo_config_set_multivar(r, key, value, NULL, 0); trace2_cmd_set_config(key, value); } @@ -3293,11 +3174,12 @@ static void validate_comment_string(const char *comment) * - the config file is removed and the lock file rename()d to it. * */ -int git_config_set_multivar_in_file_gently(const char *config_filename, - const char *key, const char *value, - const char *value_pattern, - const char *comment, - unsigned flags) +int repo_config_set_multivar_in_file_gently(struct repository *r, + const char *config_filename, + const char *key, const char *value, + const char *value_pattern, + const char *comment, + unsigned flags) { int fd = -1, in_fd = -1; int ret; @@ -3317,7 +3199,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, store.multi_replace = (flags & CONFIG_FLAGS_MULTI_REPLACE) != 0; if (!config_filename) - config_filename = filename_buf = git_pathdup("config"); + config_filename = filename_buf = repo_git_path(r, "config"); /* * The lock serves a purpose in addition to locking: the new @@ -3526,7 +3408,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, ret = 0; /* Invalidate the config cache */ - git_config_clear(); + repo_config_clear(r); out_free: rollback_lock_file(&lock); @@ -3543,12 +3425,13 @@ write_err_out: goto out_free; } -void git_config_set_multivar_in_file(const char *config_filename, - const char *key, const char *value, - const char *value_pattern, unsigned flags) +void repo_config_set_multivar_in_file(struct repository *r, + const char *config_filename, + const char *key, const char *value, + const char *value_pattern, unsigned flags) { - if (!git_config_set_multivar_in_file_gently(config_filename, key, value, - value_pattern, NULL, flags)) + if (!repo_config_set_multivar_in_file_gently(r, config_filename, key, value, + value_pattern, NULL, flags)) return; if (value) die(_("could not set '%s' to '%s'"), key, value); @@ -3556,32 +3439,27 @@ void git_config_set_multivar_in_file(const char *config_filename, die(_("could not unset '%s'"), key); } -int git_config_set_multivar_gently(const char *key, const char *value, - const char *value_pattern, unsigned flags) -{ - return repo_config_set_multivar_gently(the_repository, key, value, - value_pattern, flags); -} - int repo_config_set_multivar_gently(struct repository *r, const char *key, const char *value, const char *value_pattern, unsigned flags) { char *file = repo_git_path(r, "config"); - int res = git_config_set_multivar_in_file_gently(file, - key, value, - value_pattern, - NULL, flags); + int res = repo_config_set_multivar_in_file_gently(r, file, + key, value, + value_pattern, + NULL, flags); free(file); return res; } -void git_config_set_multivar(const char *key, const char *value, - const char *value_pattern, unsigned flags) +void repo_config_set_multivar(struct repository *r, + const char *key, const char *value, + const char *value_pattern, unsigned flags) { - git_config_set_multivar_in_file(git_path("config"), - key, value, value_pattern, - flags); + char *file = repo_git_path(r, "config"); + repo_config_set_multivar_in_file(r, file, key, value, + value_pattern, flags); + free(file); } static size_t section_name_match (const char *buf, const char *name) @@ -3643,9 +3521,11 @@ static int section_name_is_ok(const char *name) #define GIT_CONFIG_MAX_LINE_LEN (512 * 1024) /* if new_name == NULL, the section is removed instead */ -static int git_config_copy_or_rename_section_in_file(const char *config_filename, - const char *old_name, - const char *new_name, int copy) +static int repo_config_copy_or_rename_section_in_file( + struct repository *r, + const char *config_filename, + const char *old_name, + const char *new_name, int copy) { int ret = 0, remove = 0; char *filename_buf = NULL; @@ -3666,7 +3546,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename } if (!config_filename) - config_filename = filename_buf = git_pathdup("config"); + config_filename = filename_buf = repo_git_path(r, "config"); out_fd = hold_lock_file_for_update(&lock, config_filename, 0); if (out_fd < 0) { @@ -3809,28 +3689,28 @@ out_no_rollback: return ret; } -int git_config_rename_section_in_file(const char *config_filename, - const char *old_name, const char *new_name) +int repo_config_rename_section_in_file(struct repository *r, const char *config_filename, + const char *old_name, const char *new_name) { - return git_config_copy_or_rename_section_in_file(config_filename, + return repo_config_copy_or_rename_section_in_file(r, config_filename, old_name, new_name, 0); } -int git_config_rename_section(const char *old_name, const char *new_name) +int repo_config_rename_section(struct repository *r, const char *old_name, const char *new_name) { - return git_config_rename_section_in_file(NULL, old_name, new_name); + return repo_config_rename_section_in_file(r, NULL, old_name, new_name); } -int git_config_copy_section_in_file(const char *config_filename, - const char *old_name, const char *new_name) +int repo_config_copy_section_in_file(struct repository *r, const char *config_filename, + const char *old_name, const char *new_name) { - return git_config_copy_or_rename_section_in_file(config_filename, + return repo_config_copy_or_rename_section_in_file(r, config_filename, old_name, new_name, 1); } -int git_config_copy_section(const char *old_name, const char *new_name) +int repo_config_copy_section(struct repository *r, const char *old_name, const char *new_name) { - return git_config_copy_section_in_file(NULL, old_name, new_name); + return repo_config_copy_section_in_file(r, NULL, old_name, new_name); } /* @@ -26,7 +26,7 @@ struct object_id; /* git_config_parse_key() returns these negated: */ #define CONFIG_INVALID_KEY 1 #define CONFIG_NO_SECTION_OR_NAME 2 -/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */ +/* repo_config_set_gently(), repo_config_set_multivar_gently() return the above or these: */ #define CONFIG_NO_LOCK -1 #define CONFIG_INVALID_FILE 3 #define CONFIG_NO_WRITE 4 @@ -170,9 +170,9 @@ int git_default_config(const char *, const char *, /** * Read a specific file in git-config format. - * This function takes the same callback and data parameters as `git_config`. + * This function takes the same callback and data parameters as `repo_config`. * - * Unlike git_config(), this function does not respect includes. + * Unlike repo_config(), this function does not respect includes. */ int git_config_from_file(config_fn_t fn, const char *, void *); @@ -192,15 +192,26 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name, void git_config_push_parameter(const char *text); void git_config_push_env(const char *spec); int git_config_from_parameters(config_fn_t fn, void *data); -void read_early_config(config_fn_t cb, void *data); + +/* + * Read config when the Git directory has not yet been set up. In case + * `the_repository` has not yet been set up, try to discover the Git + * directory to read the configuration from. + */ +void read_early_config(struct repository *repo, config_fn_t cb, void *data); + +/* + * Read config but only enumerate system and global settings. + * Omit any repo-local, worktree-local, or command-line settings. + */ void read_very_early_config(config_fn_t cb, void *data); /** * Most programs will simply want to look up variables in all config files * that Git knows about, using the normal precedence rules. To do this, - * call `git_config` with a callback function and void data pointer. + * call `repo_config` with a callback function and void data pointer. * - * `git_config` will read all config sources in order of increasing + * `repo_config` will read all config sources in order of increasing * priority. Thus a callback should typically overwrite previously-seen * entries with new ones (e.g., if both the user-wide `~/.gitconfig` and * repo-specific `.git/config` contain `color.ui`, the config machinery @@ -210,11 +221,11 @@ void read_very_early_config(config_fn_t cb, void *data); * * Unlike git_config_from_file(), this function respects includes. */ -void git_config(config_fn_t fn, void *); +void repo_config(struct repository *r, config_fn_t fn, void *); /** * Lets the caller examine config while adjusting some of the default - * behavior of `git_config`. It should almost never be used by "regular" + * behavior of `repo_config`. It should almost never be used by "regular" * Git code that is looking up configuration variables. * It is intended for advanced callers like `git-config`, which are * intentionally tweaking the normal config-lookup process. @@ -223,12 +234,12 @@ void git_config(config_fn_t fn, void *); * - `config_source` * If this parameter is non-NULL, it specifies the source to parse for * configuration, rather than looking in the usual files. See `struct - * git_config_source` in `config.h` for details. Regular `git_config` defaults + * git_config_source` in `config.h` for details. Regular `repo_config` defaults * to `NULL`. * * - `opts` * Specify options to adjust the behavior of parsing config files. See `struct - * config_options` in `config.h` for details. As an example: regular `git_config` + * config_options` in `config.h` for details. As an example: regular `repo_config` * sets `opts.respect_includes` to `1` by default. */ int config_with_options(config_fn_t fn, void *, @@ -297,15 +308,16 @@ int git_config_pathname(char **, const char *, const char *); int git_config_expiry_date(timestamp_t *, const char *, const char *); int git_config_color(char *, const char *, const char *); -int git_config_set_in_file_gently(const char *, const char *, const char *, const char *); +int repo_config_set_in_file_gently(struct repository *r, const char *config_filename, + const char *key, const char *comment, const char *value); /** * write config values to a specific config file, takes a key/value pair as * parameter. */ -void git_config_set_in_file(const char *, const char *, const char *); +void repo_config_set_in_file(struct repository *, const char *, const char *, const char *); -int git_config_set_gently(const char *, const char *); +int repo_config_set_gently(struct repository *r, const char *, const char *); /** * Write a config value that should apply to the current worktree. If @@ -317,13 +329,13 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha /** * write config values to `.git/config`, takes a key/value pair as parameter. */ -void git_config_set(const char *, const char *); +void repo_config_set(struct repository *, const char *, const char *); int git_config_parse_key(const char *, char **, size_t *); /* * The following macros specify flag bits that alter the behavior - * of the git_config_set_multivar*() methods. + * of the repo_config_set_multivar*() methods. */ /* @@ -340,10 +352,9 @@ int git_config_parse_key(const char *, char **, size_t *); */ #define CONFIG_FLAGS_FIXED_VALUE (1 << 1) -int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned); -void git_config_set_multivar(const char *, const char *, const char *, unsigned); int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned); -int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned); +void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned); +int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned); char *git_config_prepare_comment_string(const char *); @@ -367,11 +378,12 @@ char *git_config_prepare_comment_string(const char *); * * It returns 0 on success. */ -void git_config_set_multivar_in_file(const char *config_filename, - const char *key, - const char *value, - const char *value_pattern, - unsigned flags); +void repo_config_set_multivar_in_file(struct repository *r, + const char *config_filename, + const char *key, + const char *value, + const char *value_pattern, + unsigned flags); /** * rename or remove sections in the config file @@ -379,11 +391,11 @@ void git_config_set_multivar_in_file(const char *config_filename, * If NULL is passed through `new_name` parameter, * the section will be removed from the config file. */ -int git_config_rename_section(const char *, const char *); +int repo_config_rename_section(struct repository *, const char *, const char *); -int git_config_rename_section_in_file(const char *, const char *, const char *); -int git_config_copy_section(const char *, const char *); -int git_config_copy_section_in_file(const char *, const char *, const char *); +int repo_config_rename_section_in_file(struct repository *, const char *, const char *, const char *); +int repo_config_copy_section(struct repository *, const char *, const char *); +int repo_config_copy_section_in_file(struct repository *, const char *, const char *, const char *); int git_config_system(void); int config_error_nonbool(const char *); #if defined(__GNUC__) @@ -550,39 +562,11 @@ int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *i int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest); int git_configset_get_pathname(struct config_set *cs, const char *key, char **dest); -/* Functions for reading a repository's config */ -struct repository; -void repo_config(struct repository *repo, config_fn_t fn, void *data); - /** * Run only the discover part of the repo_config_get_*() functions * below, in addition to 1 if not found, returns negative values on * error (e.g. if the key itself is invalid). */ -RESULT_MUST_BE_USED -int repo_config_get(struct repository *repo, const char *key); -int repo_config_get_value(struct repository *repo, - const char *key, const char **value); -RESULT_MUST_BE_USED -int repo_config_get_value_multi(struct repository *repo, const char *key, - const struct string_list **dest); -RESULT_MUST_BE_USED -int repo_config_get_string_multi(struct repository *repo, const char *key, - const struct string_list **dest); -int repo_config_get_string(struct repository *repo, - const char *key, char **dest); -int repo_config_get_string_tmp(struct repository *repo, - const char *key, const char **dest); -int repo_config_get_int(struct repository *repo, - const char *key, int *dest); -int repo_config_get_ulong(struct repository *repo, - const char *key, unsigned long *dest); -int repo_config_get_bool(struct repository *repo, - const char *key, int *dest); -int repo_config_get_bool_or_int(struct repository *repo, - const char *key, int *is_bool, int *dest); -int repo_config_get_maybe_bool(struct repository *repo, - const char *key, int *dest); int repo_config_get_pathname(struct repository *repo, const char *key, char **dest); @@ -598,17 +582,17 @@ void git_protected_config(config_fn_t fn, void *data); * ------------------------------- * * For programs wanting to query for specific variables in a non-callback - * manner, the config API provides two functions `git_config_get_value` - * and `git_config_get_value_multi`. They both read values from an internal + * manner, the config API provides two functions `repo_config_get_value` + * and `repo_config_get_value_multi`. They both read values from an internal * cache generated previously from reading the config files. * - * For those git_config_get*() functions that aren't documented, + * For those repo_config_get*() functions that aren't documented, * consult the corresponding repo_config_get*() function's * documentation. */ RESULT_MUST_BE_USED -int git_config_get(const char *key); +int repo_config_get(struct repository *r, const char *key); /** * Finds the highest-priority value for the configuration variable `key`, @@ -617,7 +601,7 @@ int git_config_get(const char *key); * `value`. The caller should not free or modify `value`, as it is owned * by the cache. */ -int git_config_get_value(const char *key, const char **value); +int repo_config_get_value(struct repository *r, const char *key, const char **value); /** * Finds and returns the value list, sorted in order of increasing priority @@ -628,16 +612,16 @@ int git_config_get_value(const char *key, const char **value); * owned by the cache. */ RESULT_MUST_BE_USED -int git_config_get_value_multi(const char *key, - const struct string_list **dest); -RESULT_MUST_BE_USED -int git_config_get_string_multi(const char *key, +int repo_config_get_value_multi(struct repository *r, const char *key, const struct string_list **dest); +RESULT_MUST_BE_USED +int repo_config_get_string_multi(struct repository *r, const char *key, + const struct string_list **dest); /** * Resets and invalidates the config cache. */ -void git_config_clear(void); +void repo_config_clear(struct repository *repo); /** * Allocates and copies the retrieved string into the `dest` parameter for @@ -645,14 +629,15 @@ void git_config_clear(void); * error message and returns -1. When the configuration variable `key` is * not found, returns 1 without touching `dest`. */ -int git_config_get_string(const char *key, char **dest); +int repo_config_get_string(struct repository *r, const char *key, char **dest); /** - * Similar to `git_config_get_string`, but does not allocate any new + * Similar to `repo_config_get_string`, but does not allocate any new * memory; on success `dest` will point to memory owned by the config * machinery, which could be invalidated if it is discarded and reloaded. */ -int git_config_get_string_tmp(const char *key, const char **dest); +int repo_config_get_string_tmp(struct repository *r, + const char *key, const char **dest); /** * Finds and parses the value to an integer for the configuration variable @@ -660,12 +645,13 @@ int git_config_get_string_tmp(const char *key, const char **dest); * `dest` and returns 0. When the configuration variable `key` is not found, * returns 1 without touching `dest`. */ -int git_config_get_int(const char *key, int *dest); +int repo_config_get_int(struct repository *r, const char *key, int *dest); /** - * Similar to `git_config_get_int` but for unsigned longs. + * Similar to `repo_config_get_int` but for unsigned longs. */ -int git_config_get_ulong(const char *key, unsigned long *dest); +int repo_config_get_ulong(struct repository *r, + const char *key, unsigned long *dest); /** * Finds and parses the value into a boolean value, for the configuration @@ -676,47 +662,45 @@ int git_config_get_ulong(const char *key, unsigned long *dest); * configuration variable `key` is not found, returns 1 without touching * `dest`. */ -int git_config_get_bool(const char *key, int *dest); +int repo_config_get_bool(struct repository *r, const char *key, int *dest); /** - * Similar to `git_config_get_bool`, except that integers are copied as-is, + * Similar to `repo_config_get_bool`, except that integers are copied as-is, * and `is_bool` flag is unset. */ -int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest); +int repo_config_get_bool_or_int(struct repository *r, const char *key, + int *is_bool, int *dest); /** - * Similar to `git_config_get_bool`, except that it returns -1 on error + * Similar to `repo_config_get_bool`, except that it returns -1 on error * rather than dying. */ -int git_config_get_maybe_bool(const char *key, int *dest); - -/** - * Similar to `git_config_get_string`, but expands `~` or `~user` into - * the user's home directory when found at the beginning of the path. - */ -int git_config_get_pathname(const char *key, char **dest); +int repo_config_get_maybe_bool(struct repository *r, + const char *key, int *dest); -int git_config_get_index_threads(int *dest); -int git_config_get_split_index(void); -int git_config_get_max_percent_split_change(void); +int repo_config_get_index_threads(struct repository *r, int *dest); +int repo_config_get_split_index(struct repository *r); +int repo_config_get_max_percent_split_change(struct repository *r); /* This dies if the configured or default date is in the future */ -int git_config_get_expiry(const char *key, const char **output); +int repo_config_get_expiry(struct repository *r, const char *key, char **output); /* parse either "this many days" integer, or "5.days.ago" approxidate */ -int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now); +int repo_config_get_expiry_in_days(struct repository *r, const char *key, + timestamp_t *, timestamp_t now); /** * First prints the error message specified by the caller in `err` and then * dies printing the line number and the file name of the highest priority * value for the configuration variable `key`. */ -NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3))); +NORETURN void git_die_config(struct repository *r, const char *key, const char *err, ...) + __attribute__((format(printf, 3, 4))); /** * Helper function which formats the die error message according to the * parameters entered. Used by `git_die_config()`. It can be used by callers - * handling `git_config_get_value_multi()` to print the correct error message + * handling `repo_config_get_value_multi()` to print the correct error message * for the desired value. */ NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr); @@ -725,4 +709,140 @@ NORETURN void git_die_config_linenr(const char *key, const char *filename, int l lookup_config(mapping, ARRAY_SIZE(mapping), var) int lookup_config(const char **mapping, int nr_mapping, const char *var); +# ifdef USE_THE_REPOSITORY_VARIABLE +static inline void git_config(config_fn_t fn, void *data) +{ + repo_config(the_repository, fn, data); +} + +static inline void git_config_clear(void) +{ + repo_config_clear(the_repository); +} + +static inline int git_config_get(const char *key) +{ + return repo_config_get(the_repository, key); +} + +static inline int git_config_get_value(const char *key, const char **value) +{ + return repo_config_get_value(the_repository, key, value); +} + +static inline int git_config_get_value_multi(const char *key, const struct string_list **dest) +{ + return repo_config_get_value_multi(the_repository, key, dest); +} + +static inline int git_config_get_string_multi(const char *key, + const struct string_list **dest) +{ + return repo_config_get_string_multi(the_repository, key, dest); +} + +static inline int git_config_get_string(const char *key, char **dest) +{ + return repo_config_get_string(the_repository, key, dest); +} + +static inline int git_config_get_string_tmp(const char *key, const char **dest) +{ + return repo_config_get_string_tmp(the_repository, key, dest); +} + +static inline int git_config_get_int(const char *key, int *dest) +{ + return repo_config_get_int(the_repository, key, dest); +} + +static inline int git_config_get_ulong(const char *key, unsigned long *dest) +{ + return repo_config_get_ulong(the_repository, key, dest); +} + +static inline int git_config_get_bool(const char *key, int *dest) +{ + return repo_config_get_bool(the_repository, key, dest); +} + +static inline int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest) +{ + return repo_config_get_bool_or_int(the_repository, key, is_bool, dest); +} + +static inline int git_config_get_maybe_bool(const char *key, int *dest) +{ + return repo_config_get_maybe_bool(the_repository, key, dest); +} + +static inline int git_config_get_pathname(const char *key, char **dest) +{ + return repo_config_get_pathname(the_repository, key, dest); +} + +static inline void git_config_set_in_file(const char *config_filename, + const char *key, const char *value) +{ + repo_config_set_in_file(the_repository, config_filename, key, value); +} + +static inline int git_config_set_gently(const char *key, const char *value) +{ + return repo_config_set_gently(the_repository, key, value); +} + +static inline void git_config_set(const char *key, const char *value) +{ + repo_config_set(the_repository, key, value); +} + +static inline int git_config_set_in_file_gently( + const char *config_filename, + const char *key, + const char *comment, + const char *value) +{ + return repo_config_set_in_file_gently(the_repository, config_filename, + key, comment, value); +} + +static inline int git_config_set_multivar_in_file_gently( + const char *config_filename, + const char *key, const char *value, + const char *value_pattern, + const char *comment, + unsigned flags) +{ + return repo_config_set_multivar_in_file_gently(the_repository, config_filename, + key, value, value_pattern, + comment, flags); +} + +static inline void git_config_set_multivar_in_file( + const char *config_filename, + const char *key, + const char *value, + const char *value_pattern, + unsigned flags) +{ + repo_config_set_multivar_in_file(the_repository, config_filename, + key, value, value_pattern, flags); +} + +static inline int git_config_set_multivar_gently(const char *key, const char *value, + const char *value_pattern, unsigned flags) +{ + return repo_config_set_multivar_gently(the_repository, key, value, + value_pattern, flags); +} + +static inline void git_config_set_multivar(const char *key, const char *value, + const char *value_pattern, unsigned flags) +{ + repo_config_set_multivar(the_repository, key, value, + value_pattern, flags); +} +# endif /* USE_THE_REPOSITORY_VARIABLE */ + #endif /* CONFIG_H */ diff --git a/config.mak.dev b/config.mak.dev index 5229c35484..8eca7fa228 100644 --- a/config.mak.dev +++ b/config.mak.dev @@ -54,7 +54,6 @@ ifeq ($(filter extra-all,$(DEVOPTS)),) DEVELOPER_CFLAGS += -Wno-empty-body DEVELOPER_CFLAGS += -Wno-missing-field-initializers DEVELOPER_CFLAGS += -Wno-sign-compare -DEVELOPER_CFLAGS += -Wno-unused-parameter endif endif @@ -70,7 +69,7 @@ DEVELOPER_CFLAGS += -Wno-missing-braces endif endif -# Old versions of clang complain about initializaing a +# Old versions of clang complain about initializing a # struct-within-a-struct using just "{0}" rather than "{{0}}". This # error is considered a false-positive and not worth fixing, because # new clang versions do not, so just disable it. diff --git a/config.mak.uname b/config.mak.uname index 85d63821ec..d5112168a4 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -8,7 +8,6 @@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') -uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') ifneq ($(findstring MINGW,$(uname_S)),) @@ -249,6 +248,7 @@ ifeq ($(uname_O),Cygwin) else NO_REGEX = UnfortunatelyYes endif + HAVE_DEV_TTY = YesPlease HAVE_ALLOCA_H = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes @@ -649,6 +649,7 @@ ifeq ($(uname_S),OS/390) NO_GECOS_IN_PWENT = YesPlease HAVE_STRINGS_H = YesPlease NEEDS_MODE_TRANSLATION = YesPlease + HAVE_ZOS_GET_EXECUTABLE_PATH = YesPlease endif ifeq ($(uname_S),MINGW) ifeq ($(shell expr "$(uname_R)" : '1\.'),2) @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "environment.h" @@ -1483,6 +1485,7 @@ struct child_process *git_connect(int fd[2], const char *url, free(hostandport); free(path); + child_process_clear(conn); free(conn); strbuf_release(&cmd); return NULL; diff --git a/connected.c b/connected.c index 87cc4b57a1..3099da84f3 100644 --- a/connected.c +++ b/connected.c @@ -54,7 +54,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data, strbuf_add(&idx_file, transport->pack_lockfiles.items[0].string, base_len); strbuf_addstr(&idx_file, ".idx"); - new_pack = add_packed_git(idx_file.buf, idx_file.len, 1); + new_pack = add_packed_git(the_repository, idx_file.buf, + idx_file.len, 1); strbuf_release(&idx_file); } @@ -78,7 +79,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data, for (p = get_all_packs(the_repository); p; p = p->next) { if (!p->pack_promisor) continue; - if (find_pack_entry_one(oid->hash, p)) + if (find_pack_entry_one(oid, p)) goto promisor_pack_found; } /* @@ -144,7 +145,7 @@ no_promisor_pack_found: * are sure the ref is good and not sending it to * rev-list for verification. */ - if (new_pack && find_pack_entry_one(oid->hash, new_pack)) + if (new_pack && find_pack_entry_one(oid, new_pack)) continue; if (fprintf(rev_list_in, "%s\n", oid_to_hex(oid)) < 0) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 832f46b316..8c71f5a1d0 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -970,18 +970,15 @@ if(BUILD_TESTING) add_executable(test-fake-ssh ${CMAKE_SOURCE_DIR}/t/helper/test-fake-ssh.c) target_link_libraries(test-fake-ssh common-main) -#reftable-tests -parse_makefile_for_sources(test-reftable_SOURCES "REFTABLE_TEST_OBJS") -list(TRANSFORM test-reftable_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/") - #unit-tests -add_library(unit-test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c) -add_library(unit-test-lib-oid OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/lib-oid.c) +parse_makefile_for_sources(unit-test_SOURCES "UNIT_TEST_OBJS") +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_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 unit-test-lib-oid common-main) + target_link_libraries("${unit_test}" unit-test-lib common-main) set_target_properties("${unit_test}" PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) if(MSVC) @@ -1004,12 +1001,47 @@ foreach(unit_test ${unit_test_PROGRAMS}) endif() endforeach() +parse_makefile_for_scripts(clar_test_SUITES "CLAR_TEST_SUITES" "") +list(TRANSFORM clar_test_SUITES PREPEND "${CMAKE_SOURCE_DIR}/t/unit-tests/") +list(TRANSFORM clar_test_SUITES APPEND ".c") +add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" + COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/t/unit-tests/generate-clar-decls.sh + "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" + ${clar_test_SUITES} + DEPENDS ${CMAKE_SOURCE_DIR}/t/unit-tests/generate-clar-decls.sh + ${clar_test_SUITES} + VERBATIM) +add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" + COMMAND ${SH_EXE} "${CMAKE_SOURCE_DIR}/t/unit-tests/generate-clar-suites.sh" + "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" + "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" + DEPENDS "${CMAKE_SOURCE_DIR}/t/unit-tests/generate-clar-suites.sh" + "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" + 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(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) +set_target_properties(unit-tests + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin) +if(MSVC) + set_target_properties(unit-tests + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/unit-tests/bin) + set_target_properties(unit-tests + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/unit-tests/bin) +endif() + #test-tool parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS") add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c) list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/") -add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES} ${test-reftable_SOURCES}) +add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES}) target_link_libraries(test-tool test-lib common-main) set_target_properties(test-fake-ssh test-tool @@ -1059,6 +1091,7 @@ set(DIFF diff) set(PYTHON_PATH /usr/bin/python) set(TAR tar) set(NO_CURL ) +set(NO_ICONV ) set(NO_EXPAT ) set(USE_LIBPCRE2 ) set(NO_PERL ) @@ -1072,6 +1105,10 @@ if(NOT CURL_FOUND) set(NO_CURL 1) endif() +if(NOT Iconv_FOUND) + SET(NO_ICONV 1) +endif() + if(NOT EXPAT_FOUND) set(NO_EXPAT 1) endif() @@ -1095,6 +1132,7 @@ file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "DIFF='${DIFF}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PYTHON_PATH='${PYTHON_PATH}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "TAR='${TAR}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_CURL='${NO_CURL}'\n") +file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_ICONV='${NO_ICONV}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_EXPAT='${NO_EXPAT}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PERL='${NO_PERL}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PTHREADS='${NO_PTHREADS}'\n") diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 60a22d619a..b3b6aa3bae 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2331,7 +2331,7 @@ _git_mergetool () return ;; --*) - __gitcomp "--tool= --prompt --no-prompt --gui --no-gui" + __gitcomp "--tool= --tool-help --prompt --no-prompt --gui --no-gui" return ;; esac @@ -3296,7 +3296,7 @@ __gitcomp_directories () # i.e. which are *already* part of their # sparse-checkout. Thus, normal file and directory # completion is always useless for "git - # sparse-checkout add" and is also probelmatic for + # sparse-checkout add" and is also problematic for # "git sparse-checkout set" unless using it to # strictly narrow the checkout. COMPREPLY=( "" ) @@ -3698,7 +3698,7 @@ _git_worktree () # Here we are not completing an --option, it's either the # path or a ref. case "$prev" in - -b|-B) # Complete refs for branch to be created/reseted. + -b|-B) # Complete refs for branch to be created/reset. __git_complete_refs ;; -*) # The previous word is an -o|--option without an diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 5330e769a7..6186c474ba 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -8,8 +8,8 @@ # To enable: # # 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). -# 2) Add the following line to your .bashrc/.zshrc: -# source ~/.git-prompt.sh +# 2) Add the following line to your .bashrc/.zshrc/.profile: +# . ~/.git-prompt.sh # dot path/to/this-file # 3a) Change your PS1 to call __git_ps1 as # command-substitution: # Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' @@ -30,6 +30,8 @@ # Optionally, you can supply a third argument with a printf # format string to finetune the output of the branch status # +# See notes below about compatibility with other shells. +# # The repository status will be displayed only if you are currently in a # git repository. The %s token is the placeholder for the shown status. # @@ -106,38 +108,78 @@ # directory is set up to be ignored by git, then set # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the # repository level by setting bash.hideIfPwdIgnored to "false". +# +# Compatibility with other shells (beyond bash/zsh): +# +# We require posix-ish shell plus "local" support, which is most +# shells (even pdksh), but excluding ksh93 (because no "local"). +# +# Prompt integration might differ between shells, but the gist is +# to load it once on shell init with '. path/to/git-prompt.sh', +# set GIT_PS1* vars once as needed, and either place $(__git_ps1..) +# inside PS1 once (0/1 args), or, before each prompt is displayed, +# call __git_ps1 (2/3 args) which sets PS1 with the status embedded. +# +# Many shells support the 1st method of command substitution, +# though some might need to first enable cmd substitution in PS1. +# +# When using colors, each escape sequence is wrapped between byte +# values 1 and 2 (control chars SOH, STX, respectively), which are +# invisible at the output, but for bash/readline they mark 0-width +# strings (SGR color sequences) when calculating the on-screen +# prompt width, to maintain correct input editing at the prompt. +# +# To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE +# and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not +# use markers. For instance, some shells support '\[' and '\]' as +# start/end markers in PS1 - when invoking __git_ps1 with 3/4 args, +# but it may or may not work in command substitution mode. YMMV. +# +# If the shell doesn't support 0-width markers and editing behaves +# incorrectly when using colors in __git_ps1, then, other than +# disabling color, it might be solved using multi-line prompt, +# where the git status is not at the last line, e.g.: +# PS1='\n\w \u@\h$(__git_ps1 " (%s)")\n\$ ' # check whether printf supports -v __git_printf_supports_v= printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1 +# like __git_SOH=$'\001' etc but works also in shells without $'...' +eval "$(printf ' + __git_SOH="\001" __git_STX="\002" __git_ESC="\033" + __git_LF="\n" __git_CRLF="\r\n" +')" + # stores the divergence from upstream in $p # used by GIT_PS1_SHOWUPSTREAM __git_ps1_show_upstream () { local key value - local svn_remote svn_url_pattern count n + local svn_remotes="" svn_url_pattern="" count n local upstream_type=git legacy="" verbose="" name="" + local LF="$__git_LF" - svn_remote=() # get some config options from git-config local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')" while read -r key value; do case "$key" in bash.showupstream) GIT_PS1_SHOWUPSTREAM="$value" - if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then + if [ -z "${GIT_PS1_SHOWUPSTREAM}" ]; then p="" return fi ;; svn-remote.*.url) - svn_remote[$((${#svn_remote[@]} + 1))]="$value" + svn_remotes=${svn_remotes}${value}${LF} # URI\nURI\n... svn_url_pattern="$svn_url_pattern\\|$value" upstream_type=svn+git # default upstream type is SVN if available, else git ;; esac - done <<< "$output" + done <<-OUTPUT + $output + OUTPUT # parse configuration values local option @@ -154,33 +196,45 @@ __git_ps1_show_upstream () case "$upstream_type" in git) upstream_type="@{upstream}" ;; svn*) - # get the upstream from the "git-svn-id: ..." in a commit message - # (git-svn uses essentially the same procedure internally) - local -a svn_upstream - svn_upstream=($(git log --first-parent -1 \ - --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null)) - if [[ 0 -ne ${#svn_upstream[@]} ]]; then - svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]} - svn_upstream=${svn_upstream%@*} - local n_stop="${#svn_remote[@]}" - for ((n=1; n <= n_stop; n++)); do - svn_upstream=${svn_upstream#${svn_remote[$n]}} - done + # successful svn-upstream resolution: + # - get the list of configured svn-remotes ($svn_remotes set above) + # - get the last commit which seems from one of our svn-remotes + # - confirm that it is from one of the svn-remotes + # - use $GIT_SVN_ID if set, else "git-svn" - if [[ -z "$svn_upstream" ]]; then + # get upstream from "git-svn-id: UPSTRM@N HASH" in a commit message + # (git-svn uses essentially the same procedure internally) + local svn_upstream="$( + git log --first-parent -1 \ + --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null + )" + + if [ -n "$svn_upstream" ]; then + # extract the URI, assuming --grep matched the last line + svn_upstream=${svn_upstream##*$LF} # last line + svn_upstream=${svn_upstream#*: } # UPSTRM@N HASH + svn_upstream=${svn_upstream%@*} # UPSTRM + + case ${LF}${svn_remotes} in + *"${LF}${svn_upstream}${LF}"*) + # grep indeed matched the last line - it's our remote # default branch name for checkouts with no layout: upstream_type=${GIT_SVN_ID:-git-svn} - else + ;; + *) + # the commit message includes one of our remotes, but + # it's not at the last line. is $svn_upstream junk? upstream_type=${svn_upstream#/} - fi - elif [[ "svn+git" = "$upstream_type" ]]; then + ;; + esac + elif [ "svn+git" = "$upstream_type" ]; then upstream_type="@{upstream}" fi ;; esac # Find how many commits we are ahead/behind our upstream - if [[ -z "$legacy" ]]; then + if [ -z "$legacy" ]; then count="$(git rev-list --count --left-right \ "$upstream_type"...HEAD 2>/dev/null)" else @@ -192,8 +246,8 @@ __git_ps1_show_upstream () for commit in $commits do case "$commit" in - "<"*) ((behind++)) ;; - *) ((ahead++)) ;; + "<"*) behind=$((behind+1)) ;; + *) ahead=$((ahead+1)) ;; esac done count="$behind $ahead" @@ -203,7 +257,7 @@ __git_ps1_show_upstream () fi # calculate the result - if [[ -z "$verbose" ]]; then + if [ -z "$verbose" ]; then case "$count" in "") # no upstream p="" ;; @@ -229,10 +283,10 @@ __git_ps1_show_upstream () *) # diverged from upstream upstream="|u+${count#* }-${count% *}" ;; esac - if [[ -n "$count" && -n "$name" ]]; then + if [ -n "$count" ] && [ -n "$name" ]; then __git_ps1_upstream_name=$(git rev-parse \ --abbrev-ref "$upstream_type" 2>/dev/null) - if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then + if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then upstream="$upstream \${__git_ps1_upstream_name}" else upstream="$upstream ${__git_ps1_upstream_name}" @@ -251,25 +305,29 @@ __git_ps1_show_upstream () # their own color. __git_ps1_colorize_gitstring () { - if [[ -n ${ZSH_VERSION-} ]]; then + if [ -n "${ZSH_VERSION-}" ]; then local c_red='%F{red}' local c_green='%F{green}' local c_lblue='%F{blue}' local c_clear='%f' else - # Using \001 and \002 around colors is necessary to prevent - # issues with command line editing/browsing/completion! - local c_red=$'\001\e[31m\002' - local c_green=$'\001\e[32m\002' - local c_lblue=$'\001\e[1;34m\002' - local c_clear=$'\001\e[0m\002' + # \001 (SOH) and \002 (STX) are 0-width substring markers + # which bash/readline identify while calculating the prompt + # on-screen width - to exclude 0-screen-width esc sequences. + local c_pre="${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[" + local c_post="m${GIT_PS1_COLOR_POST-$__git_STX}" + + local c_red="${c_pre}31${c_post}" + local c_green="${c_pre}32${c_post}" + local c_lblue="${c_pre}1;34${c_post}" + local c_clear="${c_pre}0${c_post}" fi - local bad_color=$c_red - local ok_color=$c_green + local bad_color="$c_red" + local ok_color="$c_green" local flags_color="$c_lblue" local branch_color="" - if [ $detached = no ]; then + if [ "$detached" = no ]; then branch_color="$ok_color" else branch_color="$bad_color" @@ -298,7 +356,7 @@ __git_ps1_colorize_gitstring () # variable, in that order. __git_eread () { - test -r "$1" && IFS=$'\r\n' read -r "$2" <"$1" + test -r "$1" && IFS=$__git_CRLF read -r "$2" <"$1" } # see if a cherry-pick or revert is in progress, if the user has committed a @@ -346,7 +404,7 @@ __git_sequencer_status () __git_ps1 () { # preserve exit status - local exit=$? + local exit="$?" local pcmode=no local detached=no local ps1pc_start='\u@\h:\w ' @@ -365,7 +423,7 @@ __git_ps1 () ;; 0|1) printf_format="${1:-$printf_format}" ;; - *) return $exit + *) return "$exit" ;; esac @@ -403,7 +461,7 @@ __git_ps1 () # incorrect.) # local ps1_expanded=yes - [ -z "${ZSH_VERSION-}" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no + [ -z "${ZSH_VERSION-}" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no [ -z "${BASH_VERSION-}" ] || shopt -q promptvars || ps1_expanded=no local repo_info rev_parse_exit_code @@ -413,29 +471,30 @@ __git_ps1 () rev_parse_exit_code="$?" if [ -z "$repo_info" ]; then - return $exit + return "$exit" fi + local LF="$__git_LF" local short_sha="" if [ "$rev_parse_exit_code" = "0" ]; then - short_sha="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" + short_sha="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" fi - local ref_format="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local inside_worktree="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local bare_repo="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local inside_gitdir="${repo_info##*$'\n'}" - local g="${repo_info%$'\n'*}" + local ref_format="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local inside_worktree="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local bare_repo="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local inside_gitdir="${repo_info##*$LF}" + local g="${repo_info%$LF*}" if [ "true" = "$inside_worktree" ] && [ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] && [ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] && git check-ignore -q . then - return $exit + return "$exit" fi local sparse="" @@ -485,14 +544,16 @@ __git_ps1 () case "$ref_format" in files) if ! __git_eread "$g/HEAD" head; then - return $exit + return "$exit" fi - if [[ $head == "ref: "* ]]; then + case $head in + "ref: "*) head="${head#ref: }" - else + ;; + *) head="" - fi + esac ;; *) head="$(git symbolic-ref HEAD 2>/dev/null)" @@ -528,8 +589,8 @@ __git_ps1 () fi local conflict="" # state indicator for unresolved conflicts - if [[ "${GIT_PS1_SHOWCONFLICTSTATE-}" == "yes" ]] && - [[ $(git ls-files --unmerged 2>/dev/null) ]]; then + if [ "${GIT_PS1_SHOWCONFLICTSTATE-}" = "yes" ] && + [ "$(git ls-files --unmerged 2>/dev/null)" ]; then conflict="|CONFLICT" fi @@ -581,10 +642,10 @@ __git_ps1 () fi fi - local z="${GIT_PS1_STATESEPARATOR-" "}" + local z="${GIT_PS1_STATESEPARATOR- }" b=${b##refs/heads/} - if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then + if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then __git_ps1_branch_name=$b b="\${__git_ps1_branch_name}" fi @@ -596,7 +657,7 @@ __git_ps1 () local f="$h$w$i$s$u$p" local gitstring="$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}" - if [ $pcmode = yes ]; then + if [ "$pcmode" = yes ]; then if [ "${__git_printf_supports_v-}" != yes ]; then gitstring=$(printf -- "$printf_format" "$gitstring") else @@ -607,5 +668,5 @@ __git_ps1 () printf -- "$printf_format" "$gitstring" fi - return $exit + return "$exit" } diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c index 6ce22a28ed..1c8310d7fe 100644 --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c @@ -141,7 +141,7 @@ static void find_username_in_item(CFDictionaryRef item) username_buf, buffer_len, ENCODING)) { - write_item("username", username_buf, buffer_len - 1); + write_item("username", username_buf, strlen(username_buf)); } free(username_buf); } diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm index 636add6968..3d061bc0b7 100644 --- a/contrib/diff-highlight/DiffHighlight.pm +++ b/contrib/diff-highlight/DiffHighlight.pm @@ -1,6 +1,6 @@ package DiffHighlight; -use 5.008001; +require v5.26; use warnings FATAL => 'all'; use strict; diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump index 47e0c557e6..3f69675961 100755 --- a/contrib/git-jump/git-jump +++ b/contrib/git-jump/git-jump @@ -44,13 +44,13 @@ open_editor() { mode_diff() { git diff --no-prefix --relative "$@" | perl -ne ' - if (m{^\+\+\+ (.*)}) { $file = $1; next } + if (m{^\+\+\+ (.*)}) { $file = $1 eq "/dev/null" ? undef : $1; next } defined($file) or next; if (m/^@@ .*?\+(\d+)/) { $line = $1; next } defined($line) or next; if (/^ /) { $line++; next } if (/^[-+]\s*(.*)/) { - print "$file:$line: $1\n"; + print "$file:$line:1: $1\n"; $line = undef; } ' diff --git a/contrib/mw-to-git/Git/Mediawiki.pm b/contrib/mw-to-git/Git/Mediawiki.pm index ff7811225e..629c0cea44 100644 --- a/contrib/mw-to-git/Git/Mediawiki.pm +++ b/contrib/mw-to-git/Git/Mediawiki.pm @@ -1,6 +1,6 @@ package Git::Mediawiki; -use 5.008001; +require v5.26; use strict; use POSIX; use Git; diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 5dab3f506c..15ae86db1b 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -946,7 +946,7 @@ cmd_split () { rev=$(git rev-parse -q --verify "$1^{commit}") || die "fatal: '$1' does not refer to a commit" else - die "fatal: you must provide exactly one revision, and optionnally a repository. Got: '$*'" + die "fatal: you must provide exactly one revision, and optionally a repository. Got: '$*'" fi repository="" if test "$#" = 2 diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index c3bd2a58b9..3c6103f6d2 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -47,7 +47,7 @@ last_commit_subject () { # pre-2.32.0 versions of 'git subtree' would write the hash of the tag # (sub1 below), instead of the commit (sub1^{commit}) in the # "git-subtree-split" trailer. -# We immitate this behaviour below using a replace ref. +# We imitate this behaviour below using a replace ref. # This function creates 3 repositories: # - $1 # - $1-sub (added as subtree "sub" in $1) @@ -324,6 +324,9 @@ static void trace_encoding(const char *context, const char *path, struct strbuf trace = STRBUF_INIT; int i; + if (!trace_want(&coe)) + return; + strbuf_addf(&trace, "%s (%s, considered %s):\n", context, path, encoding); for (i = 0; i < len && buf; ++i) { strbuf_addf( @@ -1368,6 +1371,9 @@ void reset_parsed_attributes(void) for (drv = user_convert; drv; drv = next) { next = drv->next; free((void *)drv->name); + free((void *)drv->smudge); + free((void *)drv->clean); + free((void *)drv->process); free(drv); } user_convert = NULL; diff --git a/credential.c b/credential.c index 4b1a2b94fe..6dea3859ec 100644 --- a/credential.c +++ b/credential.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "config.h" @@ -11,6 +13,8 @@ #include "strbuf.h" #include "urlmatch.h" #include "git-compat-util.h" +#include "trace2.h" +#include "repository.h" void credential_init(struct credential *c) { @@ -249,14 +253,36 @@ static char *credential_ask_one(const char *what, struct credential *c, return xstrdup(r); } -static void credential_getpass(struct credential *c) +static int credential_getpass(struct credential *c) { + int interactive; + char *value; + if (!git_config_get_maybe_bool("credential.interactive", &interactive) && + !interactive) { + trace2_data_intmax("credential", the_repository, + "interactive/skipped", 1); + return -1; + } + if (!git_config_get_string("credential.interactive", &value)) { + int same = !strcmp(value, "never"); + free(value); + if (same) { + trace2_data_intmax("credential", the_repository, + "interactive/skipped", 1); + return -1; + } + } + + trace2_region_enter("credential", "interactive", the_repository); if (!c->username) c->username = credential_ask_one("Username", c, PROMPT_ASKPASS|PROMPT_ECHO); if (!c->password) c->password = credential_ask_one("Password", c, PROMPT_ASKPASS); + trace2_region_leave("credential", "interactive", the_repository); + + return 0; } int credential_has_capability(const struct credential_capability *capa, @@ -499,8 +525,8 @@ void credential_fill(struct credential *c, int all_capabilities) c->helpers.items[i].string); } - credential_getpass(c); - if (!c->username && !c->password && !c->credential) + if (credential_getpass(c) || + (!c->username && !c->password && !c->credential)) die("unable to get password from user"); } diff --git a/csum-file.c b/csum-file.c index 8abbf01325..c203ebf11b 100644 --- a/csum-file.c +++ b/csum-file.c @@ -50,13 +50,13 @@ void hashflush(struct hashfile *f) if (offset) { if (!f->skip_hash) - the_hash_algo->update_fn(&f->ctx, f->buffer, offset); + the_hash_algo->unsafe_update_fn(&f->ctx, f->buffer, offset); flush(f, f->buffer, offset); f->offset = 0; } } -static void free_hashfile(struct hashfile *f) +void free_hashfile(struct hashfile *f) { free(f->buffer); free(f->check_buffer); @@ -73,7 +73,7 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result, if (f->skip_hash) hashclr(f->buffer, the_repository->hash_algo); else - the_hash_algo->final_fn(f->buffer, &f->ctx); + the_hash_algo->unsafe_final_fn(f->buffer, &f->ctx); if (result) hashcpy(result, f->buffer, the_repository->hash_algo); @@ -102,6 +102,15 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result, return fd; } +void discard_hashfile(struct hashfile *f) +{ + if (0 <= f->check_fd) + close(f->check_fd); + if (0 <= f->fd) + close(f->fd); + free_hashfile(f); +} + void hashwrite(struct hashfile *f, const void *buf, unsigned int count) { while (count) { @@ -119,7 +128,7 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count) * f->offset is necessarily zero. */ if (!f->skip_hash) - the_hash_algo->update_fn(&f->ctx, buf, nr); + the_hash_algo->unsafe_update_fn(&f->ctx, buf, nr); flush(f, buf, nr); } else { /* @@ -165,7 +174,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name, f->name = name; f->do_crc = 0; f->skip_hash = 0; - the_hash_algo->init_fn(&f->ctx); + the_hash_algo->unsafe_init_fn(&f->ctx); f->buffer_len = buffer_len; f->buffer = xmalloc(buffer_len); @@ -199,7 +208,7 @@ void hashfile_checkpoint(struct hashfile *f, struct hashfile_checkpoint *checkpo { hashflush(f); checkpoint->offset = f->total; - the_hash_algo->clone_fn(&checkpoint->ctx, &f->ctx); + the_hash_algo->unsafe_clone_fn(&checkpoint->ctx, &f->ctx); } int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint) @@ -210,7 +219,7 @@ int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint lseek(f->fd, offset, SEEK_SET) != offset) return -1; f->total = offset; - the_hash_algo->clone_fn(&f->ctx, &checkpoint->ctx); + the_hash_algo->unsafe_clone_fn(&f->ctx, &checkpoint->ctx); f->offset = 0; /* hashflush() was called in checkpoint */ return 0; } @@ -236,9 +245,9 @@ int hashfile_checksum_valid(const unsigned char *data, size_t total_len) if (total_len < the_hash_algo->rawsz) return 0; /* say "too short"? */ - the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, data, data_len); - the_hash_algo->final_fn(got, &ctx); + the_hash_algo->unsafe_init_fn(&ctx); + the_hash_algo->unsafe_update_fn(&ctx, data, data_len); + the_hash_algo->unsafe_final_fn(got, &ctx); return hasheq(got, data + data_len, the_repository->hash_algo); } diff --git a/csum-file.h b/csum-file.h index 566e05cbd2..7c73da0a40 100644 --- a/csum-file.h +++ b/csum-file.h @@ -46,7 +46,18 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *); struct hashfile *hashfd(int fd, const char *name); struct hashfile *hashfd_check(const char *name); struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp); + +/* + * Free the hashfile without flushing its contents to disk. This only + * needs to be called when not calling `finalize_hashfile()`. + */ +void free_hashfile(struct hashfile *f); + +/* + * Finalize the hashfile by flushing data to disk and free'ing it. + */ int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int); +void discard_hashfile(struct hashfile *); void hashwrite(struct hashfile *, const void *, unsigned int); void hashflush(struct hashfile *f); void crc32_begin(struct hashfile *); @@ -1,7 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "config.h" #include "environment.h" +#include "gettext.h" #include "path.h" #include "pkt-line.h" #include "protocol.h" @@ -149,6 +152,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi) size_t rlen; const char *path; const char *dir; + unsigned enter_repo_flags; dir = directory; @@ -239,14 +243,15 @@ static const char *path_ok(const char *directory, struct hostinfo *hi) dir = rpath; } - path = enter_repo(dir, strict_paths); + enter_repo_flags = strict_paths ? ENTER_REPO_STRICT : 0; + path = enter_repo(dir, enter_repo_flags); if (!path && base_path && base_path_relaxed) { /* * if we fail and base_path_relaxed is enabled, try without * prefixing the base path */ dir = directory; - path = enter_repo(dir, strict_paths); + path = enter_repo(dir, enter_repo_flags); } if (!path) { @@ -1175,13 +1180,13 @@ static int service_loop(struct socketlist *socklist) struct credentials; -static void drop_privileges(struct credentials *cred) +static void drop_privileges(struct credentials *cred UNUSED) { /* nothing */ } -static struct credentials *prepare_credentials(const char *user_name, - const char *group_name) +static struct credentials *prepare_credentials(const char *user_name UNUSED, + const char *group_name UNUSED) { die("--user not supported on this platform"); } @@ -1306,17 +1311,20 @@ int cmd_main(int argc, const char **argv) continue; } if (skip_prefix(arg, "--timeout=", &v)) { - timeout = atoi(v); + if (strtoul_ui(v, 10, &timeout)) + die(_("invalid timeout '%s', expecting a non-negative integer"), v); continue; } if (skip_prefix(arg, "--init-timeout=", &v)) { - init_timeout = atoi(v); + if (strtoul_ui(v, 10, &init_timeout)) + die(_("invalid init-timeout '%s', expecting a non-negative integer"), v); continue; } if (skip_prefix(arg, "--max-connections=", &v)) { - max_connections = atoi(v); + if (strtol_i(v, 10, &max_connections)) + die(_("invalid max-connections '%s', expecting an integer"), v); if (max_connections < 0) - max_connections = 0; /* unlimited */ + max_connections = 0; /* unlimited */ continue; } if (!strcmp(arg, "--strict-paths")) { diff --git a/delta-islands.c b/delta-islands.c index ffe1ca2814..8443551259 100644 --- a/delta-islands.c +++ b/delta-islands.c @@ -390,7 +390,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name, rl->hash += sha_core; } -static int find_island_for_ref(const char *refname, const struct object_id *oid, +static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb) { struct island_load_data *ild = cb; diff --git a/diff-lib.c b/diff-lib.c index 7a1eb63757..3cf353946f 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -308,8 +308,7 @@ static void diff_index_show_file(struct rev_info *revs, oid, oid_valid, ce->name, dirty_submodule); } -static int get_stat_data(const struct index_state *istate, - const struct cache_entry *ce, +static int get_stat_data(const struct cache_entry *ce, const struct object_id **oidp, unsigned int *modep, int cached, int match_missing, @@ -352,7 +351,6 @@ static void show_new_file(struct rev_info *revs, const struct object_id *oid; unsigned int mode; unsigned dirty_submodule = 0; - struct index_state *istate = revs->diffopt.repo->index; if (new_file && S_ISSPARSEDIR(new_file->ce_mode)) { diff_tree_oid(NULL, &new_file->oid, new_file->name, &revs->diffopt); @@ -363,7 +361,7 @@ static void show_new_file(struct rev_info *revs, * New file in the index: it might actually be different in * the working tree. */ - if (get_stat_data(istate, new_file, &oid, &mode, cached, match_missing, + if (get_stat_data(new_file, &oid, &mode, cached, match_missing, &dirty_submodule, &revs->diffopt) < 0) return; @@ -379,7 +377,6 @@ static int show_modified(struct rev_info *revs, unsigned int mode, oldmode; const struct object_id *oid; unsigned dirty_submodule = 0; - struct index_state *istate = revs->diffopt.repo->index; assert(S_ISSPARSEDIR(old_entry->ce_mode) == S_ISSPARSEDIR(new_entry->ce_mode)); @@ -395,7 +392,7 @@ static int show_modified(struct rev_info *revs, return 0; } - if (get_stat_data(istate, new_entry, &oid, &mode, cached, match_missing, + if (get_stat_data(new_entry, &oid, &mode, cached, match_missing, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old_entry, @@ -664,6 +661,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt) repo_init_revisions(opt->repo, &revs, NULL); copy_pathspec(&revs.prune_data, &opt->pathspec); + diff_free(&revs.diffopt); revs.diffopt = *opt; revs.diffopt.no_free = 1; @@ -704,7 +702,7 @@ int index_differs_from(struct repository *r, return (has_changes != 0); } -static struct strbuf *idiff_prefix_cb(struct diff_options *opt UNUSED, void *data) +static const char *idiff_prefix_cb(struct diff_options *opt UNUSED, void *data) { return data; } @@ -719,7 +717,7 @@ void show_interdiff(const struct object_id *oid1, const struct object_id *oid2, opts.output_format = DIFF_FORMAT_PATCH; opts.output_prefix = idiff_prefix_cb; strbuf_addchars(&prefix, ' ', indent); - opts.output_prefix_data = &prefix; + opts.output_prefix_data = prefix.buf; diff_setup_done(&opts); diff_tree_oid(oid1, oid2, "", &opts); diff --git a/diff-no-index.c b/diff-no-index.c index 3a8965672c..c5fb06e6d1 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -362,7 +362,7 @@ int diff_no_index(struct rev_info *revs, * The return code for --no-index imitates diff(1): * 0 = no changes, 1 = changes, else error */ - ret = diff_result_code(&revs->diffopt); + ret = diff_result_code(revs); out: for (i = 0; i < ARRAY_SIZE(to_free); i++) @@ -12,6 +12,7 @@ #include "environment.h" #include "gettext.h" #include "tempfile.h" +#include "revision.h" #include "quote.h" #include "diff.h" #include "diffcore.h" @@ -29,6 +30,7 @@ #include "merge-ll.h" #include "string-list.h" #include "strvec.h" +#include "tmp-objdir.h" #include "graph.h" #include "oid-array.h" #include "packfile.h" @@ -441,8 +443,10 @@ int git_diff_ui_config(const char *var, const char *value, } if (!strcmp(var, "diff.wordregex")) return git_config_string(&diff_word_regex_cfg, var, value); - if (!strcmp(var, "diff.orderfile")) + if (!strcmp(var, "diff.orderfile")) { + FREE_AND_NULL(diff_order_file_cfg); return git_config_pathname(&diff_order_file_cfg, var, value); + } if (!strcmp(var, "diff.ignoresubmodules")) { if (!value) @@ -2313,12 +2317,9 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) const char *diff_line_prefix(struct diff_options *opt) { - struct strbuf *msgbuf; - if (!opt->output_prefix) - return ""; - - msgbuf = opt->output_prefix(opt, opt->output_prefix_data); - return msgbuf->buf; + return opt->output_prefix ? + opt->output_prefix(opt, opt->output_prefix_data) : + ""; } static unsigned long sane_truncate_line(char *line, unsigned long len) @@ -3565,6 +3566,7 @@ static void builtin_diff(const char *name_a, show_submodule_diff_summary(o, one->path ? one->path : two->path, &one->oid, &two->oid, two->dirty_submodule); + o->found_changes = 1; return; } else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF && (!one->mode || S_ISGITLINK(one->mode)) && @@ -3573,6 +3575,7 @@ static void builtin_diff(const char *name_a, show_submodule_inline_diff(o, one->path ? one->path : two->path, &one->oid, &two->oid, two->dirty_submodule); + o->found_changes = 1; return; } @@ -3671,6 +3674,7 @@ static void builtin_diff(const char *name_a, emit_diff_symbol(o, DIFF_SYMBOL_BINARY_FILES, sb.buf, sb.len, 0); strbuf_release(&sb); + o->found_changes = 1; goto free_ab_and_return; } if (fill_mmfile(o->repo, &mf1, one) < 0 || @@ -4037,7 +4041,8 @@ static int reuse_worktree_file(struct index_state *istate, * objects however would tend to be slower as they need * to be individually opened and inflated. */ - if (!FAST_WORKING_DIRECTORY && !want_file && has_object_pack(oid)) + if (!FAST_WORKING_DIRECTORY && !want_file && + has_object_pack(istate->repo, oid)) return 0; /* @@ -4587,6 +4592,9 @@ static void run_diff_cmd(const struct external_diff *pgm, builtin_diff(name, other ? other : name, one, two, xfrm_msg, must_show_header, o, complete_rewrite); + if (p->status == DIFF_STATUS_COPIED || + p->status == DIFF_STATUS_RENAMED) + o->found_changes = 1; } else { fprintf(o->file, "* Unmerged path %s\n", name); o->found_changes = 1; @@ -4770,7 +4778,7 @@ void repo_diff_setup(struct repository *r, struct diff_options *options) if (diff_indent_heuristic) DIFF_XDL_SET(options, INDENT_HEURISTIC); - options->orderfile = diff_order_file_cfg; + options->orderfile = xstrdup_or_null(diff_order_file_cfg); if (!options->flags.ignore_submodule_set) options->flags.ignore_untracked_in_submodules = 1; @@ -5390,7 +5398,6 @@ static int diff_opt_line_prefix(const struct option *opt, BUG_ON_OPT_NEG(unset); options->line_prefix = optarg; - options->line_prefix_length = strlen(options->line_prefix); graph_setup_line_prefix(options); return 0; } @@ -5464,9 +5471,13 @@ static int diff_opt_ignore_regex(const struct option *opt, regex_t *regex; BUG_ON_OPT_NEG(unset); + regex = xmalloc(sizeof(*regex)); - if (regcomp(regex, arg, REG_EXTENDED | REG_NEWLINE)) + if (regcomp(regex, arg, REG_EXTENDED | REG_NEWLINE)) { + free(regex); return error(_("invalid regex given to -I: '%s'"), arg); + } + ALLOC_GROW(options->ignore_regex, options->ignore_regex_nr + 1, options->ignore_regex_alloc); options->ignore_regex[options->ignore_regex_nr++] = regex; @@ -5969,11 +5980,18 @@ void diff_free_filepair(struct diff_filepair *p) free(p); } -void diff_free_queue(struct diff_queue_struct *q) +void diff_queue_init(struct diff_queue_struct *q) +{ + struct diff_queue_struct blank = DIFF_QUEUE_INIT; + memcpy(q, &blank, sizeof(*q)); +} + +void diff_queue_clear(struct diff_queue_struct *q) { for (int i = 0; i < q->nr; i++) diff_free_filepair(q->queue[i]); free(q->queue); + diff_queue_init(q); } const char *diff_aligned_abbrev(const struct object_id *oid, int len) @@ -6537,8 +6555,7 @@ int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int struct diff_queue_struct *q = &diff_queued_diff; int result = diff_get_patch_id(options, oid, diff_header_only); - diff_free_queue(q); - DIFF_QUEUE_CLEAR(q); + diff_queue_clear(q); return result; } @@ -6713,6 +6730,17 @@ void diff_free(struct diff_options *options) if (options->no_free) return; + if (options->objfind) { + oidset_clear(options->objfind); + FREE_AND_NULL(options->objfind); + } + + FREE_AND_NULL(options->orderfile); + for (size_t i = 0; i < options->anchors_nr; i++) + free(options->anchors[i]); + FREE_AND_NULL(options->anchors); + options->anchors_nr = options->anchors_alloc = 0; + diff_free_file(options); diff_free_ignore_regex(options); clear_pathspec(&options->pathspec); @@ -6810,8 +6838,7 @@ void diff_flush(struct diff_options *options) } free_queue: - diff_free_queue(q); - DIFF_QUEUE_CLEAR(q); + diff_queue_clear(q); diff_free(options); /* @@ -6842,9 +6869,7 @@ static void diffcore_apply_filter(struct diff_options *options) { int i; struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; - - DIFF_QUEUE_CLEAR(&outq); + struct diff_queue_struct outq = DIFF_QUEUE_INIT; if (!options->filter) return; @@ -6937,8 +6962,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) { int i; struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; - DIFF_QUEUE_CLEAR(&outq); + struct diff_queue_struct outq = DIFF_QUEUE_INIT; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; @@ -7069,10 +7093,16 @@ void diffcore_std(struct diff_options *options) options->found_follow = 0; } -int diff_result_code(struct diff_options *opt) +int diff_result_code(struct rev_info *revs) { + struct diff_options *opt = &revs->diffopt; int result = 0; + if (revs->remerge_diff) { + tmp_objdir_destroy(revs->remerge_objdir); + revs->remerge_objdir = NULL; + } + diff_warn_rename_limit("diff.renameLimit", opt->needed_rename_limit, opt->degraded_cc_to_c); @@ -94,7 +94,7 @@ typedef void (*add_remove_fn_t)(struct diff_options *options, typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, struct diff_options *options, void *data); -typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data); +typedef const char *(*diff_prefix_fn_t)(struct diff_options *opt, void *data); #define DIFF_FORMAT_RAW 0x0001 #define DIFF_FORMAT_DIFFSTAT 0x0002 @@ -235,7 +235,7 @@ enum diff_submodule_format { * diffcore library with. */ struct diff_options { - const char *orderfile; + char *orderfile; /* * "--rotate-to=<file>" would start showing at <file> and when @@ -274,7 +274,6 @@ struct diff_options { const char *single_follow; const char *a_prefix, *b_prefix; const char *line_prefix; - size_t line_prefix_length; /** * collection of boolean options that affects the operation, but some do @@ -648,7 +647,7 @@ int do_diff_cache(const struct object_id *, struct diff_options *); int diff_flush_patch_id(struct diff_options *, struct object_id *, int); void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx); -int diff_result_code(struct diff_options *); +int diff_result_code(struct rev_info *); int diff_no_index(struct rev_info *, int implicit_no_index, int, const char **); diff --git a/diffcore-break.c b/diffcore-break.c index 831b66b5c3..c4c2173f30 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -131,7 +131,7 @@ static int should_break(struct repository *r, void diffcore_break(struct repository *r, int break_score) { struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; + struct diff_queue_struct outq = DIFF_QUEUE_INIT; /* When the filepair has this much edit (insert and delete), * it is first considered to be a rewrite and broken into a @@ -178,8 +178,6 @@ void diffcore_break(struct repository *r, int break_score) if (!merge_score) merge_score = DEFAULT_MERGE_SCORE; - DIFF_QUEUE_CLEAR(&outq); - for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; int score; @@ -266,8 +264,8 @@ static void merge_broken(struct diff_filepair *p, * in the resulting tree. */ d->one->rename_used++; - diff_free_filespec_data(d->two); - diff_free_filespec_data(c->one); + free_filespec(d->two); + free_filespec(c->one); free(d); free(c); } @@ -275,11 +273,9 @@ static void merge_broken(struct diff_filepair *p, void diffcore_merge_broken(void) { struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; + struct diff_queue_struct outq = DIFF_QUEUE_INIT; int i, j; - DIFF_QUEUE_CLEAR(&outq); - for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; if (!p) diff --git a/diffcore-order.c b/diffcore-order.c index e7d20ebd2d..912513d3e6 100644 --- a/diffcore-order.c +++ b/diffcore-order.c @@ -14,8 +14,7 @@ static void prepare_order(const char *orderfile) { int cnt, pass; struct strbuf sb = STRBUF_INIT; - void *map; - char *cp, *endp; + const char *cp, *endp; ssize_t sz; if (order) @@ -24,14 +23,13 @@ static void prepare_order(const char *orderfile) sz = strbuf_read_file(&sb, orderfile, 0); if (sz < 0) die_errno(_("failed to read orderfile '%s'"), orderfile); - map = strbuf_detach(&sb, NULL); - endp = (char *) map + sz; + endp = sb.buf + sz; for (pass = 0; pass < 2; pass++) { cnt = 0; - cp = map; + cp = sb.buf; while (cp < endp) { - char *ep; + const char *ep; for (ep = cp; ep < endp && *ep != '\n'; ep++) ; /* cp to ep has one line */ @@ -40,12 +38,7 @@ static void prepare_order(const char *orderfile) else if (pass == 0) cnt++; else { - if (*ep == '\n') { - *ep = 0; - order[cnt] = cp; - } else { - order[cnt] = xmemdupz(cp, ep - cp); - } + order[cnt] = xmemdupz(cp, ep - cp); cnt++; } if (ep < endp) @@ -57,6 +50,8 @@ static void prepare_order(const char *orderfile) ALLOC_ARRAY(order, cnt); } } + + strbuf_release(&sb); } static int match_order(const char *path) diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index b195fa4eb3..43fef8e8ba 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -182,9 +182,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o, regex_t *regexp, kwset_t kws, pickaxe_fn fn) { int i; - struct diff_queue_struct outq; - - DIFF_QUEUE_CLEAR(&outq); + struct diff_queue_struct outq = DIFF_QUEUE_INIT; if (o->pickaxe_opts & DIFF_PICKAXE_ALL) { /* Showing the whole changeset if needle exists */ diff --git a/diffcore-rename.c b/diffcore-rename.c index fab45b10d7..1b1c1a6a1f 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -933,7 +933,7 @@ static int find_basename_matches(struct diff_options *options, * spend more cycles to find similarities between files, so it may * be less likely that this heuristic is wanted. If someone is * doing break detection, that means they do not want filename - * similarity to imply any form of content similiarity, and thus + * similarity to imply any form of content similarity, and thus * this heuristic would definitely be incompatible. */ @@ -1388,7 +1388,7 @@ void diffcore_rename_extended(struct diff_options *options, int detect_rename = options->detect_rename; int minimum_score = options->rename_score; struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; + struct diff_queue_struct outq = DIFF_QUEUE_INIT; struct diff_score *mx; int i, j, rename_count, skip_unmodified = 0; int num_destinations, dst_cnt; @@ -1534,7 +1534,7 @@ void diffcore_rename_extended(struct diff_options *options, * - remove ones not found in relevant_sources * and * - remove ones in relevant_sources which are needed only - * for directory renames IF no ancestory directory + * for directory renames IF no ancestry directory * actually needs to know any more individual path * renames under them */ @@ -1638,7 +1638,6 @@ void diffcore_rename_extended(struct diff_options *options, * are recorded in rename_dst. The original list is still in *q. */ trace2_region_enter("diff", "write back to queue", options->repo); - DIFF_QUEUE_CLEAR(&outq); for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; struct diff_filepair *pair_to_free = NULL; diff --git a/diffcore-rotate.c b/diffcore-rotate.c index 533986cf63..73ca20b331 100644 --- a/diffcore-rotate.c +++ b/diffcore-rotate.c @@ -10,7 +10,7 @@ void diffcore_rotate(struct diff_options *opt) { struct diff_queue_struct *q = &diff_queued_diff; - struct diff_queue_struct outq; + struct diff_queue_struct outq = DIFF_QUEUE_INIT; int rotate_to, i; if (!q->nr) @@ -31,7 +31,6 @@ void diffcore_rotate(struct diff_options *opt) return; } - DIFF_QUEUE_CLEAR(&outq); rotate_to = i; for (i = rotate_to; i < q->nr; i++) diff --git a/diffcore.h b/diffcore.h index 1701ed50b9..2feb325031 100644 --- a/diffcore.h +++ b/diffcore.h @@ -153,18 +153,16 @@ struct diff_queue_struct { int nr; }; -#define DIFF_QUEUE_CLEAR(q) \ - do { \ - (q)->queue = NULL; \ - (q)->nr = (q)->alloc = 0; \ - } while (0) +#define DIFF_QUEUE_INIT { 0 } + +void diff_queue_init(struct diff_queue_struct *q); +void diff_queue_clear(struct diff_queue_struct *q); extern struct diff_queue_struct diff_queued_diff; struct diff_filepair *diff_queue(struct diff_queue_struct *, struct diff_filespec *, struct diff_filespec *); void diff_q(struct diff_queue_struct *, struct diff_filepair *); -void diff_free_queue(struct diff_queue_struct *q); /* dir_rename_relevance: the reason we want rename information for a dir */ enum dir_rename_relevance { @@ -20,6 +20,7 @@ #include "object-store-ll.h" #include "path.h" #include "refs.h" +#include "repository.h" #include "wildmatch.h" #include "pathspec.h" #include "utf8.h" @@ -1055,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir) { int i; dir->valid = 0; + for (size_t i = 0; i < dir->untracked_nr; i++) + free(dir->untracked[i]); dir->untracked_nr = 0; for (i = 0; i < dir->dirs_nr; i++) do_invalidate_gitignore(dir->dirs[i]); @@ -1082,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc, uc->dir_invalidated++; dir->valid = 0; + for (size_t i = 0; i < dir->untracked_nr; i++) + free(dir->untracked[i]); dir->untracked_nr = 0; for (i = 0; i < dir->dirs_nr; i++) dir->dirs[i]->recurse = 0; @@ -2135,8 +2140,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir, */ state = path_none; } else { - int i; - for (i = old_ignored_nr + 1; i<dir->ignored_nr; ++i) + for (int i = old_ignored_nr; i < dir->ignored_nr; i++) FREE_AND_NULL(dir->ignored[i]); dir->ignored_nr = old_ignored_nr; } @@ -2148,8 +2152,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir, */ if ((dir->flags & DIR_SHOW_IGNORED_TOO) && !(dir->flags & DIR_KEEP_UNTRACKED_CONTENTS)) { - int i; - for (i = old_untracked_nr + 1; i<dir->nr; ++i) + for (int i = old_untracked_nr; i < dir->nr; i++) FREE_AND_NULL(dir->entries[i]); dir->nr = old_untracked_nr; } @@ -2838,7 +2841,7 @@ static const char *get_ident_string(void) return sb.buf; if (uname(&uts) < 0) die_errno(_("failed to get kernel name and information")); - strbuf_addf(&sb, "Location %s, system %s", get_git_work_tree(), + strbuf_addf(&sb, "Location %s, system %s", repo_get_work_tree(the_repository), uts.sysname); return sb.buf; } @@ -2869,14 +2872,14 @@ static void set_untracked_ident(struct untracked_cache *uc) static unsigned new_untracked_cache_flags(struct index_state *istate) { struct repository *repo = istate->repo; - char *val; + const char *val; /* * This logic is coordinated with the setting of these flags in * wt-status.c#wt_status_collect_untracked(), and the evaluation * of the config setting in commit.c#git_status_config() */ - if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) && + if (!repo_config_get_string_tmp(repo, "status.showuntrackedfiles", &val) && !strcmp(val, "all")) return 0; @@ -3574,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked, * for safety.. */ if (!untracked->valid) { + for (size_t i = 0; i < untracked->untracked_nr; i++) + free(untracked->untracked[i]); untracked->untracked_nr = 0; untracked->check_only = 0; } @@ -3906,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc, { uc->dir_invalidated++; ucd->valid = 0; + for (size_t i = 0; i < ucd->untracked_nr; i++) + free(ucd->untracked[i]); ucd->untracked_nr = 0; } @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "advice.h" @@ -133,14 +135,17 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer, return launch_specified_editor(git_sequence_editor(), path, buffer, env); } -int strbuf_edit_interactively(struct strbuf *buffer, const char *path, +int strbuf_edit_interactively(struct repository *r, + struct strbuf *buffer, const char *path, const char *const *env) { - char *path2 = NULL; + struct strbuf sb = STRBUF_INIT; int fd, res = 0; - if (!is_absolute_path(path)) - path = path2 = xstrdup(git_path("%s", path)); + if (!is_absolute_path(path)) { + strbuf_repo_git_path(&sb, r, "%s", path); + path = sb.buf; + } fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) @@ -157,6 +162,6 @@ int strbuf_edit_interactively(struct strbuf *buffer, const char *path, unlink(path); } - free(path2); + strbuf_release(&sb); return res; } @@ -1,6 +1,7 @@ #ifndef EDITOR_H #define EDITOR_H +struct repository; struct strbuf; const char *git_editor(void); @@ -28,7 +29,7 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer, * * If `path` is relative, it refers to a file in the `.git` directory. */ -int strbuf_edit_interactively(struct strbuf *buffer, const char *path, - const char *const *env); +int strbuf_edit_interactively(struct repository *r, struct strbuf *buffer, + const char *path, const char *const *env); #endif diff --git a/environment.c b/environment.c index 5cea2c9f54..8389a27270 100644 --- a/environment.c +++ b/environment.c @@ -22,15 +22,9 @@ #include "fmt-merge-msg.h" #include "commit.h" #include "strvec.h" -#include "object-file.h" -#include "object-store-ll.h" #include "path.h" -#include "replace-object.h" -#include "tmp-objdir.h" #include "chdir-notify.h" #include "setup.h" -#include "shallow.h" -#include "trace.h" #include "write-or-die.h" int trust_executable_bit = 1; @@ -40,9 +34,7 @@ int has_symlinks = 1; int minimum_abbrev = 4, default_abbrev = -1; int ignore_case; int assume_unchanged; -int prefer_symlink_refs; int is_bare_repository_cfg = -1; /* unspecified */ -int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int repository_format_precious_objects; char *git_commit_encoding; @@ -57,9 +49,6 @@ int fsync_object_files = -1; int use_fsync = -1; enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT; enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT; -size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE; -size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT; -size_t delta_base_cache_limit = 96 * 1024 * 1024; unsigned long big_file_threshold = 512 * 1024 * 1024; char *editor_program; char *askpass_program; @@ -75,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS #endif enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; -char *notes_ref_name; int grafts_keep_true_parents; int core_apply_sparse_checkout; int core_sparse_checkout_cone; @@ -83,7 +71,6 @@ int sparse_expect_files_outside_of_patterns; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ unsigned long pack_size_limit_cfg; -enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET; int max_allowed_tree_depth = #ifdef _MSC_VER /* @@ -114,6 +101,7 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT; * that is subject to stripspace. */ const char *comment_line_str = "#"; +char *comment_line_str_to_free; int auto_comment_line_char; /* Parallel index stat data preload? */ @@ -122,8 +110,6 @@ int core_preload_index = 1; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; -static char *git_namespace; - /* * Repository-local GIT_* environment variables; see environment.h for details. */ @@ -146,27 +132,6 @@ const char * const local_repo_env[] = { NULL }; -static char *expand_namespace(const char *raw_namespace) -{ - struct strbuf buf = STRBUF_INIT; - struct strbuf **components, **c; - - if (!raw_namespace || !*raw_namespace) - return xstrdup(""); - - strbuf_addstr(&buf, raw_namespace); - components = strbuf_split(&buf, '/'); - strbuf_reset(&buf); - for (c = components; *c; c++) - if (strcmp((*c)->buf, "/") != 0) - strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf); - strbuf_list_free(components); - if (check_refname_format(buf.buf, 0)) - die(_("bad git namespace path \"%s\""), raw_namespace); - strbuf_addch(&buf, '/'); - return strbuf_detach(&buf, NULL); -} - const char *getenv_safe(struct strvec *argv, const char *name) { const char *value = getenv(name); @@ -178,47 +143,10 @@ const char *getenv_safe(struct strvec *argv, const char *name) return argv->v[argv->nr - 1]; } -void setup_git_env(const char *git_dir) -{ - char *git_replace_ref_base; - const char *shallow_file; - const char *replace_ref_base; - struct set_gitdir_args args = { NULL }; - struct strvec to_free = STRVEC_INIT; - - args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT); - args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT); - args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT); - args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT); - args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT); - if (getenv(GIT_QUARANTINE_ENVIRONMENT)) { - args.disable_ref_updates = 1; - } - - repo_set_gitdir(the_repository, git_dir, &args); - strvec_clear(&to_free); - - if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) - disable_replace_refs(); - replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT); - git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base - : "refs/replace/"); - update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base); - - free(git_namespace); - git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT)); - shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); - if (shallow_file) - set_alternate_shallow_file(the_repository, shallow_file, 0); - - if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0)) - fetch_if_missing = 0; -} - int is_bare_repository(void) { /* if core.bare is not 'false', let's see if there is a work tree */ - return is_bare_repository_cfg && !get_git_work_tree(); + return is_bare_repository_cfg && !repo_get_work_tree(the_repository); } int have_git_dir(void) @@ -227,156 +155,45 @@ int have_git_dir(void) || the_repository->gitdir; } -const char *get_git_dir(void) -{ - if (!the_repository->gitdir) - BUG("git environment hasn't been setup"); - return the_repository->gitdir; -} - -const char *get_git_common_dir(void) -{ - if (!the_repository->commondir) - BUG("git environment hasn't been setup"); - return the_repository->commondir; -} - const char *get_git_namespace(void) { - if (!git_namespace) - BUG("git environment hasn't been setup"); - return git_namespace; -} + static const char *namespace; -const char *strip_namespace(const char *namespaced_ref) -{ - const char *out; - if (skip_prefix(namespaced_ref, get_git_namespace(), &out)) - return out; - return NULL; -} - -static int git_work_tree_initialized; + struct strbuf buf = STRBUF_INIT; + struct strbuf **components, **c; + const char *raw_namespace; -/* - * Note. This works only before you used a work tree. This was added - * primarily to support git-clone to work in a new repository it just - * created, and is not meant to flip between different work trees. - */ -void set_git_work_tree(const char *new_work_tree) -{ - if (git_work_tree_initialized) { - struct strbuf realpath = STRBUF_INIT; + if (namespace) + return namespace; - strbuf_realpath(&realpath, new_work_tree, 1); - new_work_tree = realpath.buf; - if (strcmp(new_work_tree, the_repository->worktree)) - die("internal error: work tree has already been set\n" - "Current worktree: %s\nNew worktree: %s", - the_repository->worktree, new_work_tree); - strbuf_release(&realpath); - return; + raw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT); + if (!raw_namespace || !*raw_namespace) { + namespace = ""; + return namespace; } - git_work_tree_initialized = 1; - repo_set_worktree(the_repository, new_work_tree); -} - -const char *get_git_work_tree(void) -{ - return the_repository->worktree; -} - -const char *get_object_directory(void) -{ - if (!the_repository->objects->odb) - BUG("git environment hasn't been setup"); - return the_repository->objects->odb->path; -} - -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) -{ - int fd; - /* - * we let the umask do its job, don't try to be more - * restrictive except to remove write permission. - */ - int mode = 0444; - git_path_buf(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); - safe_create_leading_directories(temp_filename->buf); - return xmkstemp_mode(temp_filename->buf, mode); -} - -int odb_pack_keep(const char *name) -{ - int fd; - - fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600); - if (0 <= fd) - return fd; - - /* slow path */ - safe_create_leading_directories_const(name); - return open(name, O_RDWR|O_CREAT|O_EXCL, 0600); -} - -char *get_index_file(void) -{ - if (!the_repository->index_file) - BUG("git environment hasn't been setup"); - return the_repository->index_file; -} - -char *get_graft_file(struct repository *r) -{ - if (!r->graft_file) - BUG("git environment hasn't been setup"); - return r->graft_file; -} -static void set_git_dir_1(const char *path) -{ - xsetenv(GIT_DIR_ENVIRONMENT, path, 1); - setup_git_env(path); -} + strbuf_addstr(&buf, raw_namespace); + components = strbuf_split(&buf, '/'); + strbuf_reset(&buf); + for (c = components; *c; c++) + if (strcmp((*c)->buf, "/") != 0) + strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf); + strbuf_list_free(components); + if (check_refname_format(buf.buf, 0)) + die(_("bad git namespace path \"%s\""), raw_namespace); + strbuf_addch(&buf, '/'); -static void update_relative_gitdir(const char *name UNUSED, - const char *old_cwd, - const char *new_cwd, - void *data UNUSED) -{ - char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir()); - struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb(); + namespace = strbuf_detach(&buf, NULL); - trace_printf_key(&trace_setup_key, - "setup: move $GIT_DIR to '%s'", - path); - set_git_dir_1(path); - if (tmp_objdir) - tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd); - free(path); + return namespace; } -void set_git_dir(const char *path, int make_realpath) +const char *strip_namespace(const char *namespaced_ref) { - struct strbuf realpath = STRBUF_INIT; - - if (make_realpath) { - strbuf_realpath(&realpath, path, 1); - path = realpath.buf; - } - - set_git_dir_1(path); - if (!is_absolute_path(path)) - chdir_notify_register(NULL, update_relative_gitdir, NULL); - - strbuf_release(&realpath); + const char *out; + if (skip_prefix(namespaced_ref, get_git_namespace(), &out)) + return out; + return NULL; } const char *get_log_output_encoding(void) diff --git a/environment.h b/environment.h index e9f01d4d11..2f43340f0b 100644 --- a/environment.h +++ b/environment.h @@ -1,21 +1,7 @@ #ifndef ENVIRONMENT_H #define ENVIRONMENT_H -struct repository; -struct strvec; - -/* - * The character that begins a commented line in user-editable file - * that is subject to stripspace. - */ -extern const char *comment_line_str; -extern int auto_comment_line_char; - -/* - * Wrapper of getenv() that returns a strdup value. This value is kept - * in argv to be freed later. - */ -const char *getenv_safe(struct strvec *argv, const char *name); +#include "repo-settings.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR" @@ -86,6 +72,8 @@ const char *getenv_safe(struct strvec *argv, const char *name); */ #define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE" +#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" + /* * Repository-local GIT_* environment variables; these will be cleared * when git spawns a sub-process that runs inside another repository. @@ -94,6 +82,50 @@ const char *getenv_safe(struct strvec *argv, const char *name); */ extern const char * const local_repo_env[]; +struct strvec; + +/* + * Wrapper of getenv() that returns a strdup value. This value is kept + * in argv to be freed later. + */ +const char *getenv_safe(struct strvec *argv, const char *name); + +/* + * Should we print an ellipsis after an abbreviated SHA-1 value + * when doing diff-raw output or indicating a detached HEAD? + */ +int print_sha1_ellipsis(void); + +/* + * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value). + */ +int use_optional_locks(void); + +const char *get_git_namespace(void); +const char *strip_namespace(const char *namespaced_ref); + +/* + * TODO: All the below state either explicitly or implicitly relies on + * `the_repository`. We should eventually get rid of these and make the + * dependency on a repository explicit: + * + * - `setup_git_env()` ideally shouldn't exist as it modifies global state, + * namely the environment. The current process shouldn't ever access that + * state via envvars though, but should instead consult a `struct + * repository`. When spawning new processes, we would ideally also pass a + * `struct repository` and then set up the environment variables for the + * child process, only. + * + * - `have_git_dir()` should not have to exist at all. Instead, we should + * decide on whether or not we have a `struct repository`. + * + * - All the global config variables should become tied to a repository. Like + * this, we'd correctly honor repository-local configuration and be able to + * distinguish configuration values from different repositories. + * + * Please do not add new global config variables here. + */ +# ifdef USE_THE_REPOSITORY_VARIABLE void setup_git_env(const char *git_dir); /* @@ -102,21 +134,19 @@ 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; -const char *get_git_dir(void); -const char *get_git_common_dir(void); -const char *get_object_directory(void); -char *get_index_file(void); -char *get_graft_file(struct repository *r); -void set_git_dir(const char *path, int make_realpath); -const char *get_git_namespace(void); -const char *strip_namespace(const char *namespaced_ref); -const char *get_git_work_tree(void); -void set_git_work_tree(const char *tree); - -#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" /* Environment bits from configuration mechanism */ extern int trust_executable_bit; @@ -126,8 +156,6 @@ extern int has_symlinks; extern int minimum_abbrev, default_abbrev; extern int ignore_case; extern int assume_unchanged; -extern int prefer_symlink_refs; -extern int warn_ambiguous_refs; extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; @@ -137,21 +165,10 @@ extern int zlib_compression_level; extern int pack_compression_level; extern size_t packed_git_window_size; extern size_t packed_git_limit; -extern size_t delta_base_cache_limit; extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; extern int max_allowed_tree_depth; -/* - * 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 core_preload_index; extern int precomposed_unicode; extern int protect_hfs; @@ -161,25 +178,13 @@ extern int core_apply_sparse_checkout; extern int core_sparse_checkout_cone; extern int sparse_expect_files_outside_of_patterns; -/* - * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value). - */ -int use_optional_locks(void); - -enum log_refs_config { - LOG_REFS_UNSET = -1, - LOG_REFS_NONE = 0, - LOG_REFS_NORMAL, - LOG_REFS_ALWAYS -}; -extern enum log_refs_config log_all_ref_updates; - enum rebase_setup_type { AUTOREBASE_NEVER = 0, AUTOREBASE_LOCAL, AUTOREBASE_REMOTE, AUTOREBASE_ALWAYS }; +extern enum rebase_setup_type autorebase; enum push_default_type { PUSH_DEFAULT_NOTHING = 0, @@ -189,38 +194,18 @@ enum push_default_type { PUSH_DEFAULT_CURRENT, PUSH_DEFAULT_UNSPECIFIED }; - -extern enum rebase_setup_type autorebase; extern enum push_default_type push_default; enum object_creation_mode { OBJECT_CREATION_USES_HARDLINKS = 0, OBJECT_CREATION_USES_RENAMES = 1 }; - extern enum object_creation_mode object_creation_mode; -extern char *notes_ref_name; - extern int grafts_keep_true_parents; extern int repository_format_precious_objects; -/* - * Create a temporary file rooted in the object database directory, or - * die on failure. The filename is taken from "pattern", which should have the - * usual "XXXXXX" trailer, and the resulting filename is written into the - * "template" buffer. Returns the open descriptor. - */ -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); - -/* - * Create a pack .keep file named "name" (which should generally be the output - * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on - * error. - */ -int odb_pack_keep(const char *name); - const char *get_log_output_encoding(void); const char *get_commit_output_encoding(void); @@ -232,9 +217,12 @@ extern char *askpass_program; extern char *excludes_file; /* - * Should we print an ellipsis after an abbreviated SHA-1 value - * when doing diff-raw output or indicating a detached HEAD? + * The character that begins a commented line in user-editable file + * that is subject to stripspace. */ -int print_sha1_ellipsis(void); +extern const char *comment_line_str; +extern char *comment_line_str_to_free; +extern int auto_comment_line_char; -#endif +# endif /* USE_THE_REPOSITORY_VARIABLE */ +#endif /* ENVIRONMENT_H */ diff --git a/exec-cmd.c b/exec-cmd.c index 909777f61f..507e67d528 100644 --- a/exec-cmd.c +++ b/exec-cmd.c @@ -150,6 +150,25 @@ static int git_get_exec_path_darwin(struct strbuf *buf) } #endif /* HAVE_NS_GET_EXECUTABLE_PATH */ +#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH +/* + * Resolves the executable path from current program's directory and name. + * + * Returns 0 on success, -1 on failure. + */ +static int git_get_exec_path_zos(struct strbuf *buf) +{ + char *dir = __getprogramdir(); + char *exe = getprogname(); + if (dir && exe) { + strbuf_addf(buf, "%s/%s", dir, exe); + return 0; + } + return -1; +} + +#endif /* HAVE_ZOS_GET_EXECUTABLE_PATH */ + #ifdef HAVE_WPGMPTR /* * Resolves the executable path by using the global variable _wpgmptr. @@ -206,6 +225,10 @@ static int git_get_exec_path(struct strbuf *buf, const char *argv0) git_get_exec_path_wpgmptr(buf) && #endif /* HAVE_WPGMPTR */ +#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH + git_get_exec_path_zos(buf) && +#endif /*HAVE_ZOS_GET_EXECUTABLE_PATH */ + git_get_exec_path_from_argv0(buf, argv0)) { return -1; } diff --git a/fetch-pack.c b/fetch-pack.c index 732511604b..c095f3a84b 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -122,29 +122,41 @@ static void for_each_cached_alternate(struct fetch_negotiator *negotiator, cb(negotiator, cache.items[i]); } -static struct commit *deref_without_lazy_fetch_extended(const struct object_id *oid, - int mark_tags_complete, - enum object_type *type, - unsigned int oi_flags) +static void die_in_commit_graph_only(const struct object_id *oid) { - struct object_info info = { .typep = type }; + die(_("You are attempting to fetch %s, which is in the commit graph file but not in the object database.\n" + "This is probably due to repo corruption.\n" + "If you are attempting to repair this repo corruption by refetching the missing object, use 'git fetch --refetch' with the missing object."), + oid_to_hex(oid)); +} + +static struct commit *deref_without_lazy_fetch(const struct object_id *oid, + int mark_tags_complete_and_check_obj_db) +{ + enum object_type type; + struct object_info info = { .typep = &type }; struct commit *commit; commit = lookup_commit_in_graph(the_repository, oid); - if (commit) + if (commit) { + if (mark_tags_complete_and_check_obj_db) { + if (!has_object(the_repository, oid, 0)) + die_in_commit_graph_only(oid); + } return commit; + } while (1) { if (oid_object_info_extended(the_repository, oid, &info, - oi_flags)) + OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK)) return NULL; - if (*type == OBJ_TAG) { + if (type == OBJ_TAG) { struct tag *tag = (struct tag *) parse_object(the_repository, oid); if (!tag->tagged) return NULL; - if (mark_tags_complete) + if (mark_tags_complete_and_check_obj_db) tag->object.flags |= COMPLETE; oid = &tag->tagged->oid; } else { @@ -152,7 +164,7 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id * } } - if (*type == OBJ_COMMIT) { + if (type == OBJ_COMMIT) { struct commit *commit = lookup_commit(the_repository, oid); if (!commit || repo_parse_commit(the_repository, commit)) return NULL; @@ -162,16 +174,6 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id * return NULL; } - -static struct commit *deref_without_lazy_fetch(const struct object_id *oid, - int mark_tags_complete) -{ - enum object_type type; - unsigned flags = OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK; - return deref_without_lazy_fetch_extended(oid, mark_tags_complete, - &type, flags); -} - static int rev_list_insert_ref(struct fetch_negotiator *negotiator, const struct object_id *oid) { @@ -183,6 +185,7 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator, } static int rev_list_insert_ref_oid(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) @@ -610,6 +613,7 @@ static int mark_complete(const struct object_id *oid) } static int mark_complete_oid(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) @@ -1612,7 +1616,7 @@ static void receive_packfile_uris(struct packet_reader *reader, while (packet_reader_read(reader) == PACKET_READ_NORMAL) { if (reader->pktlen < the_hash_algo->hexsz || reader->line[the_hash_algo->hexsz] != ' ') - die("expected '<hash> <uri>', got: %s\n", reader->line); + die("expected '<hash> <uri>', got: %s", reader->line); string_list_append(uris, reader->line); } @@ -1837,7 +1841,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, string_list_append_nodup(pack_lockfiles, xstrfmt("%s/pack/pack-%s.keep", - get_object_directory(), + repo_get_object_directory(the_repository), packname)); } string_list_clear(&packfile_uris, 0); @@ -1853,8 +1857,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, return ref; } -static int fetch_pack_config_cb(const char *var, const char *value, - const struct config_context *ctx, void *cb) +int fetch_pack_fsck_config(const char *var, const char *value, + struct strbuf *msg_types) { const char *msg_id; @@ -1862,9 +1866,9 @@ static int fetch_pack_config_cb(const char *var, const char *value, char *path ; if (git_config_pathname(&path, var, value)) - return 1; - strbuf_addf(&fsck_msg_types, "%cskiplist=%s", - fsck_msg_types.len ? ',' : '=', path); + return 0; + strbuf_addf(msg_types, "%cskiplist=%s", + msg_types->len ? ',' : '=', path); free(path); return 0; } @@ -1873,14 +1877,24 @@ static int fetch_pack_config_cb(const char *var, const char *value, if (!value) return config_error_nonbool(var); if (is_valid_msg_type(msg_id, value)) - strbuf_addf(&fsck_msg_types, "%c%s=%s", - fsck_msg_types.len ? ',' : '=', msg_id, value); + strbuf_addf(msg_types, "%c%s=%s", + msg_types->len ? ',' : '=', msg_id, value); else warning("Skipping unknown msg id '%s'", msg_id); return 0; } - return git_default_config(var, value, ctx, cb); + return 1; +} + +static int fetch_pack_config_cb(const char *var, const char *value, + const struct config_context *ctx, void *cb) +{ + int ret = fetch_pack_fsck_config(var, value, &fsck_msg_types); + if (ret > 0) + return git_default_config(var, value, ctx, cb); + + return ret; } static void fetch_pack_config(void) @@ -2225,7 +2239,10 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips, trace2_region_leave("fetch-pack", "negotiate_using_fetch", the_repository); trace2_data_intmax("negotiate_using_fetch", the_repository, "total_rounds", negotiation_round); + clear_common_flag(acked_commits); + object_array_clear(&nt_object_array); + negotiator.release(&negotiator); strbuf_release(&req_buf); } diff --git a/fetch-pack.h b/fetch-pack.h index b5c579cdae..9d3470366f 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -106,4 +106,15 @@ int report_unmatched_refs(struct ref **sought, int nr_sought); */ int fetch_pack_fsck_objects(void); +/* + * Check if the provided config variable pertains to fetch fsck and if so append + * the configuration to the provided strbuf. + * + * When a fetch fsck config option is successfully processed the function + * returns 0. If the provided config option is unrelated to fetch fsck, 1 is + * returned. Errors return -1. + */ +int fetch_pack_fsck_config(const char *var, const char *value, + struct strbuf *msg_types); + #endif @@ -205,7 +205,7 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values) if (!strcmp(buf, "skiplist")) { if (equal == len) die("skiplist requires a path"); - oidset_parse_file(&options->skiplist, buf + equal + 1, + oidset_parse_file(&options->skip_oids, buf + equal + 1, the_repository->hash_algo); buf += len + 1; continue; @@ -223,15 +223,18 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values) static int object_on_skiplist(struct fsck_options *opts, const struct object_id *oid) { - return opts && oid && oidset_contains(&opts->skiplist, oid); + return opts && oid && oidset_contains(&opts->skip_oids, oid); } -__attribute__((format (printf, 5, 6))) -static int report(struct fsck_options *options, - const struct object_id *oid, enum object_type object_type, - enum fsck_msg_id msg_id, const char *fmt, ...) +/* + * Provide the common functionality for either fscking refs or objects. + * It will get the current msg error type and call the error_func callback + * which is registered in the "fsck_options" struct. + */ +static int fsck_vreport(struct fsck_options *options, + void *fsck_report, + enum fsck_msg_id msg_id, const char *fmt, va_list ap) { - va_list ap; struct strbuf sb = STRBUF_INIT; enum fsck_msg_type msg_type = fsck_msg_type(msg_id, options); int result; @@ -239,9 +242,6 @@ static int report(struct fsck_options *options, if (msg_type == FSCK_IGNORE) return 0; - if (object_on_skiplist(options, oid)) - return 0; - if (msg_type == FSCK_FATAL) msg_type = FSCK_ERROR; else if (msg_type == FSCK_INFO) @@ -250,16 +250,49 @@ static int report(struct fsck_options *options, prepare_msg_ids(); strbuf_addf(&sb, "%s: ", msg_id_info[msg_id].camelcased); - va_start(ap, fmt); strbuf_vaddf(&sb, fmt, ap); - result = options->error_func(options, oid, object_type, + result = options->error_func(options, fsck_report, msg_type, msg_id, sb.buf); strbuf_release(&sb); + + return result; +} + +__attribute__((format (printf, 5, 6))) +static int report(struct fsck_options *options, + const struct object_id *oid, enum object_type object_type, + enum fsck_msg_id msg_id, const char *fmt, ...) +{ + va_list ap; + struct fsck_object_report report = { + .oid = oid, + .object_type = object_type + }; + int result; + + if (object_on_skiplist(options, oid)) + return 0; + + va_start(ap, fmt); + result = fsck_vreport(options, &report, msg_id, fmt, ap); va_end(ap); return result; } +int fsck_report_ref(struct fsck_options *options, + struct fsck_ref_report *report, + enum fsck_msg_id msg_id, + const char *fmt, ...) +{ + va_list ap; + int result; + va_start(ap, fmt); + result = fsck_vreport(options, report, msg_id, fmt, ap); + va_end(ap); + return result; +} + void fsck_enable_object_names(struct fsck_options *options) { if (!options->object_names) @@ -1200,13 +1233,15 @@ int fsck_buffer(const struct object_id *oid, enum object_type type, type); } -int fsck_error_function(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type UNUSED, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id UNUSED, - const char *message) +int fsck_objects_error_function(struct fsck_options *o, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) { + struct fsck_object_report *report = fsck_report; + const struct object_id *oid = report->oid; + if (msg_type == FSCK_WARN) { warning("object %s: %s", fsck_describe_object(o, oid), message); return 0; @@ -1215,6 +1250,32 @@ int fsck_error_function(struct fsck_options *o, return 1; } +int fsck_refs_error_function(struct fsck_options *options UNUSED, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) +{ + struct fsck_ref_report *report = fsck_report; + struct strbuf sb = STRBUF_INIT; + int ret = 0; + + strbuf_addstr(&sb, report->path); + + if (report->oid) + strbuf_addf(&sb, " -> (%s)", oid_to_hex(report->oid)); + else if (report->referent) + strbuf_addf(&sb, " -> (%s)", report->referent); + + if (msg_type == FSCK_WARN) + warning("%s: %s", sb.buf, message); + else + ret = error("%s: %s", sb.buf, message); + + strbuf_release(&sb); + return ret; +} + static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done, enum fsck_msg_id msg_missing, enum fsck_msg_id msg_type, struct fsck_options *options, const char *blob_type) @@ -1234,7 +1295,7 @@ static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done, buf = repo_read_object_file(the_repository, oid, &type, &size); if (!buf) { - if (is_promisor_object(oid)) + if (is_promisor_object(the_repository, oid)) continue; ret |= report(options, oid, OBJ_BLOB, msg_missing, @@ -1270,6 +1331,17 @@ int fsck_finish(struct fsck_options *options) return ret; } +void fsck_options_clear(struct fsck_options *options) +{ + free(options->msg_type); + oidset_clear(&options->skip_oids); + oidset_clear(&options->gitmodules_found); + oidset_clear(&options->gitmodules_done); + oidset_clear(&options->gitattributes_found); + oidset_clear(&options->gitattributes_done); + kh_clear_oid_map(options->object_names); +} + int git_fsck_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { @@ -1303,16 +1375,17 @@ int git_fsck_config(const char *var, const char *value, * Custom error callbacks that are used in more than one place. */ -int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id, - const char *message) +int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message) { if (msg_id == FSCK_MSG_GITMODULES_MISSING) { - puts(oid_to_hex(oid)); + struct fsck_object_report *report = fsck_report; + puts(oid_to_hex(report->oid)); return 0; } - return fsck_error_function(o, oid, object_type, msg_type, msg_id, message); + return fsck_objects_error_function(o, fsck_report, + msg_type, msg_id, message); } @@ -31,6 +31,10 @@ enum fsck_msg_type { FUNC(BAD_NAME, ERROR) \ FUNC(BAD_OBJECT_SHA1, ERROR) \ FUNC(BAD_PARENT_SHA1, ERROR) \ + FUNC(BAD_REF_CONTENT, ERROR) \ + FUNC(BAD_REF_FILETYPE, ERROR) \ + FUNC(BAD_REF_NAME, ERROR) \ + FUNC(BAD_REFERENT_NAME, ERROR) \ FUNC(BAD_TIMEZONE, ERROR) \ FUNC(BAD_TREE, ERROR) \ FUNC(BAD_TREE_SHA1, ERROR) \ @@ -82,6 +86,10 @@ enum fsck_msg_type { FUNC(MAILMAP_SYMLINK, INFO) \ FUNC(BAD_TAG_NAME, INFO) \ FUNC(MISSING_TAGGER_ENTRY, INFO) \ + FUNC(SYMLINK_REF, INFO) \ + FUNC(REF_MISSING_NEWLINE, INFO) \ + FUNC(SYMREF_TARGET_IS_NOT_A_REF, INFO) \ + FUNC(TRAILING_REF_CONTENT, INFO) \ /* ignored (elevated when requested) */ \ FUNC(EXTRA_HEADER_ENTRY, IGNORE) @@ -114,29 +122,49 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type); typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type, void *data, struct fsck_options *options); -/* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */ +/* + * Callback for reporting errors either for objects or refs. The "fsck_report" + * is a generic pointer that can be used to pass any information. + */ typedef int (*fsck_error)(struct fsck_options *o, - const struct object_id *oid, enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message); -int fsck_error_function(struct fsck_options *o, - const struct object_id *oid, enum object_type object_type, - enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, - const char *message); -int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id, - const char *message); +int fsck_objects_error_function(struct fsck_options *o, + void *fsck_report, + enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, + const char *message); +int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message); + +int fsck_refs_error_function(struct fsck_options *options, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message); + +struct fsck_object_report { + const struct object_id *oid; + enum object_type object_type; +}; + +struct fsck_ref_report { + const char *path; + const struct object_id *oid; + const char *referent; +}; struct fsck_options { fsck_walk_func walk; fsck_error error_func; - unsigned strict:1; + unsigned strict; + unsigned verbose; enum fsck_msg_type *msg_type; - struct oidset skiplist; + struct oidset skip_oids; struct oidset gitmodules_found; struct oidset gitmodules_done; struct oidset gitattributes_found; @@ -145,12 +173,12 @@ struct fsck_options { }; #define FSCK_OPTIONS_DEFAULT { \ - .skiplist = OIDSET_INIT, \ + .skip_oids = OIDSET_INIT, \ .gitmodules_found = OIDSET_INIT, \ .gitmodules_done = OIDSET_INIT, \ .gitattributes_found = OIDSET_INIT, \ .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_error_function \ + .error_func = fsck_objects_error_function \ } #define FSCK_OPTIONS_STRICT { \ .strict = 1, \ @@ -158,7 +186,7 @@ struct fsck_options { .gitmodules_done = OIDSET_INIT, \ .gitattributes_found = OIDSET_INIT, \ .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_error_function, \ + .error_func = fsck_objects_error_function, \ } #define FSCK_OPTIONS_MISSING_GITMODULES { \ .strict = 1, \ @@ -166,7 +194,10 @@ struct fsck_options { .gitmodules_done = OIDSET_INIT, \ .gitattributes_found = OIDSET_INIT, \ .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_error_cb_print_missing_gitmodules, \ + .error_func = fsck_objects_error_cb_print_missing_gitmodules, \ +} +#define FSCK_REFS_OPTIONS_DEFAULT { \ + .error_func = fsck_refs_error_function, \ } /* descend in all linked child objects @@ -210,6 +241,21 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer, int fsck_finish(struct fsck_options *options); /* + * Clear the fsck_options struct, freeing any allocated memory. + */ +void fsck_options_clear(struct fsck_options *options); + +/* + * Report an error or warning for refs. + */ +__attribute__((format (printf, 4, 5))) +int fsck_report_ref(struct fsck_options *options, + struct fsck_ref_report *report, + enum fsck_msg_id msg_id, + const char *fmt, ...); + + +/* * Subsystem for storing human-readable names for each object. * * If fsck_enable_object_names() has not been called, all other functions are diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index e818583420..a6587a8972 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -7,7 +7,7 @@ #include "fsmonitor-path-utils.h" /* - * We keep this structure defintion private and have getters + * We keep this structure definition private and have getters * for all fields so that we can lazy load it as needed. */ struct fsmonitor_settings { diff --git a/fsmonitor.c b/fsmonitor.c index 2b17d60bbb..309a2541cb 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "dir.h" @@ -6,6 +8,7 @@ #include "fsmonitor.h" #include "fsmonitor-ipc.h" #include "name-hash.h" +#include "repository.h" #include "run-command.h" #include "strbuf.h" #include "trace2.h" @@ -167,7 +170,7 @@ static int query_fsmonitor_hook(struct repository *r, strvec_pushf(&cp.args, "%d", version); strvec_pushf(&cp.args, "%s", last_update); cp.use_shell = 1; - cp.dir = get_git_work_tree(); + cp.dir = repo_get_work_tree(the_repository); trace2_region_enter("fsm_hook", "query", NULL); @@ -244,7 +247,7 @@ static size_t handle_using_name_hash_icase( * technically this is a tracked file or a sparse-directory. * It should not have any entries in the untracked-cache, so * we should not need to use the case-corrected spelling to - * invalidate the the untracked-cache. So we may not need to + * invalidate the untracked-cache. So we may not need to * do this. For now, I'm going to be conservative and always * do it; we can revisit this later. */ diff --git a/git-archimport.perl b/git-archimport.perl index f5a317b899..6d0169cb6a 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -54,7 +54,7 @@ and can contain multiple, unrelated branches. =cut -use 5.008001; +require v5.26; use strict; use warnings; use Getopt::Std; diff --git a/git-compat-util.h b/git-compat-util.h index 71b4d23f03..a06d4f3809 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -195,6 +195,19 @@ struct strbuf; #define _NETBSD_SOURCE 1 #define _SGI_SOURCE 1 +/* + * UNUSED marks a function parameter that is always unused. It also + * can be used to annotate a function, a variable, or a type that is + * always unused. + * + * A callback interface may dictate that a function accepts a + * parameter at that position, but the implementation of the function + * may not need to use the parameter. In such a case, mark the parameter + * with UNUSED. + * + * When a parameter may be used or unused, depending on conditional + * compilation, consider using MAYBE_UNUSED instead. + */ #if GIT_GNUC_PREREQ(4, 5) #define UNUSED __attribute__((unused)) \ __attribute__((deprecated ("parameter declared as UNUSED"))) @@ -649,6 +662,17 @@ static inline int git_has_dir_sep(const char *path) #define RESULT_MUST_BE_USED #endif +/* + * MAYBE_UNUSED marks a function parameter that may be unused, but + * whose use is not an error. It also can be used to annotate a + * function, a variable, or a type that may be unused. + * + * Depending on a configuration, all uses of such a thing may become + * #ifdef'ed away. Marking it with UNUSED would give a warning in a + * compilation where it is indeed used, and not marking it at all + * would give a warning in a compilation where it is unused. In such + * a case, MAYBE_UNUSED is the appropriate annotation to use. + */ #define MAYBE_UNUSED __attribute__((__unused__)) #include "compat/bswap.h" @@ -1503,26 +1527,6 @@ int cmd_main(int, const char **); int common_exit(const char *file, int line, int code); #define exit(code) exit(common_exit(__FILE__, __LINE__, (code))) -/* - * You can mark a stack variable with UNLEAK(var) to avoid it being - * reported as a leak by tools like LSAN or valgrind. The argument - * should generally be the variable itself (not its address and not what - * it points to). It's safe to use this on pointers which may already - * have been freed, or on pointers which may still be in use. - * - * Use this _only_ for a variable that leaks by going out of scope at - * program exit (so only from cmd_* functions or their direct helpers). - * Normal functions, especially those which may be called multiple - * times, should actually free their memory. This is only meant as - * an annotation, and does nothing in non-leak-checking builds. - */ -#ifdef SUPPRESS_ANNOTATED_LEAKS -void unleak_memory(const void *ptr, size_t len); -#define UNLEAK(var) unleak_memory(&(var), sizeof(var)) -#else -#define UNLEAK(var) do {} while (0) -#endif - #define z_const #include <zlib.h> diff --git a/git-curl-compat.h b/git-curl-compat.h index e1d0bdd273..703756ba85 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -29,104 +29,6 @@ */ /** - * CURL_SOCKOPT_OK was added in 7.21.5, released in April 2011. - */ -#if LIBCURL_VERSION_NUM < 0x071505 -#define CURL_SOCKOPT_OK 0 -#endif - -/** - * CURLOPT_TCP_KEEPALIVE was added in 7.25.0, released in March 2012. - */ -#if LIBCURL_VERSION_NUM >= 0x071900 -#define GITCURL_HAVE_CURLOPT_TCP_KEEPALIVE 1 -#endif - - -/** - * CURLOPT_LOGIN_OPTIONS was added in 7.34.0, released in December - * 2013. - * - * If we start requiring 7.34.0 we might also be able to remove the - * code conditional on USE_CURL_FOR_IMAP_SEND in imap-send.c, see - * 1e16b255b95 (git-imap-send: use libcurl for implementation, - * 2014-11-09) and the check it added for "072200" in the Makefile. - - */ -#if LIBCURL_VERSION_NUM >= 0x072200 -#define GIT_CURL_HAVE_CURLOPT_LOGIN_OPTIONS 1 -#endif - -/** - * CURL_SSLVERSION_TLSv1_[012] was added in 7.34.0, released in - * December 2013. - */ -#if LIBCURL_VERSION_NUM >= 0x072200 -#define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0 -#endif - -/** - * CURLOPT_PINNEDPUBLICKEY was added in 7.39.0, released in November - * 2014. CURLE_SSL_PINNEDPUBKEYNOTMATCH was added in that same version. - */ -#if LIBCURL_VERSION_NUM >= 0x072c00 -#define GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY 1 -#define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1 -#endif - -/** - * CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015. - * - * The CURL_HTTP_VERSION_2 alias (but not CURL_HTTP_VERSION_2_0) has - * always been a macro, not an enum field (checked on curl version - * 7.78.0) - */ -#if LIBCURL_VERSION_NUM >= 0x072b00 -#define GIT_CURL_HAVE_CURL_HTTP_VERSION_2 1 -#endif - -/** - * CURLSSLOPT_NO_REVOKE was added in 7.44.0, released in August 2015. - * - * The CURLSSLOPT_NO_REVOKE is, has always been a macro, not an enum - * field (checked on curl version 7.78.0) - */ -#if LIBCURL_VERSION_NUM >= 0x072c00 -#define GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE 1 -#endif - -/** - * CURLOPT_PROXY_CAINFO was added in 7.52.0, released in August 2017. - */ -#if LIBCURL_VERSION_NUM >= 0x073400 -#define GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO 1 -#endif - -/** - * CURLOPT_PROXY_{KEYPASSWD,SSLCERT,SSLKEY} was added in 7.52.0, - * released in August 2017. - */ -#if LIBCURL_VERSION_NUM >= 0x073400 -#define GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD 1 -#endif - -/** - * CURL_SSLVERSION_TLSv1_3 was added in 7.53.0, released in February - * 2017. - */ -#if LIBCURL_VERSION_NUM >= 0x073400 -#define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_3 1 -#endif - -/** - * CURLSSLSET_{NO_BACKENDS,OK,TOO_LATE,UNKNOWN_BACKEND} were added in - * 7.56.0, released in September 2017. - */ -#if LIBCURL_VERSION_NUM >= 0x073800 -#define GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS -#endif - -/** * Versions before curl 7.66.0 (September 2019) required manually setting the * transfer-encoding for a streaming POST; after that this is handled * automatically. diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 1e03ba94d1..edf02f9964 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -1,6 +1,6 @@ #!/usr/bin/perl -use 5.008001; +require v5.26; use strict; use warnings; use Getopt::Std; diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 211ec8459a..e10ad5334e 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -13,7 +13,7 @@ # The head revision is on branch "origin" by default. # You can change that with the '-o' option. -use 5.008001; +require v5.26; use strict; use warnings; use Getopt::Long; diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 124f598bdc..a4ad9a5d2d 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -15,7 +15,7 @@ #### #### -use 5.008001; +require v5.26; use strict; use warnings; use bytes; diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh index dd0c9a5b7f..d32e47cc09 100755 --- a/git-difftool--helper.sh +++ b/git-difftool--helper.sh @@ -61,9 +61,7 @@ launch_merge_tool () { export BASE eval $GIT_DIFFTOOL_EXTCMD '"$LOCAL"' '"$REMOTE"' else - initialize_merge_tool "$merge_tool" - # ignore the error from the above --- run_merge_tool - # will diagnose unusable tool by itself + initialize_merge_tool "$merge_tool" || exit 1 run_merge_tool "$merge_tool" fi } @@ -87,9 +85,7 @@ if test -n "$GIT_DIFFTOOL_DIRDIFF" then LOCAL="$1" REMOTE="$2" - initialize_merge_tool "$merge_tool" - # ignore the error from the above --- run_merge_tool - # will diagnose unusable tool by itself + initialize_merge_tool "$merge_tool" || exit 1 run_merge_tool "$merge_tool" false status=$? diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 11379f8ad3..208dc2817c 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -207,8 +207,17 @@ You must stage at least 1 file before you can commit. # -- A message is required. # - set msg [string trim [$ui_comm get 1.0 end]] + set msg [$ui_comm get 1.0 end] + # Strip trailing whitespace regsub -all -line {[ \t\r]+$} $msg {} msg + # Strip comment lines + regsub -all {(^|\n)#[^\n]*} $msg {\1} msg + # Strip leading empty lines + regsub {^\n*} $msg {} msg + # Compress consecutive empty lines + regsub -all {\n{3,}} $msg "\n\n" msg + # Strip trailing empty line + regsub {\n\n$} $msg "\n" msg if {$msg eq {}} { error_popup [mc "Please supply a commit message. diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl index e688b016ef..8b8c16b1d6 100644 --- a/git-gui/lib/mergetool.tcl +++ b/git-gui/lib/mergetool.tcl @@ -272,8 +272,25 @@ proc merge_resolve_tool2 {} { } } default { - error_popup [mc "Unsupported merge tool '%s'" $tool] - return + set tool_cmd [get_config mergetool.$tool.cmd] + if {$tool_cmd ne {}} { + if {([string first {[} $tool_cmd] != -1) || ([string first {]} $tool_cmd] != -1)} { + error_popup [mc "Unable to process square brackets in \"mergetool.%s.cmd\" configuration option. + +Please remove the square brackets." $tool] + return + } else { + set cmdline {} + foreach command_part $tool_cmd { + lappend cmdline [subst -nobackslashes -nocommands $command_part] + } + } + } else { + error_popup [mc "Unsupported merge tool '%s'. + +To use this tool, configure \"mergetool.%s.cmd\" as shown in the git-config manual page." $tool $tool] + return + } } } diff --git a/git-instaweb.sh b/git-instaweb.sh index 994431c887..8dbe21d588 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -612,7 +612,7 @@ python_conf() { ln -sf "$root/static" "$fqgitdir/gitweb/$httpd_only/" # generate a standalone 'python http.server' script in $fqgitdir/gitweb - # This asumes that python is in user's $PATH + # This assumes that python is in user's $PATH # This script is Python 2 and 3 compatible cat > "$fqgitdir/gitweb/gitweb.py" <<EOF #!/usr/bin/env python diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh index 1ff26170ff..11ea181259 100644 --- a/git-mergetool--lib.sh +++ b/git-mergetool--lib.sh @@ -159,7 +159,7 @@ check_unchanged () { } valid_tool () { - setup_tool "$1" && return 0 + setup_tool "$1" 2>/dev/null && return 0 cmd=$(get_merge_tool_cmd "$1") test -n "$cmd" } @@ -250,7 +250,12 @@ setup_tool () { . "$MERGE_TOOLS_DIR/${tool%[0-9]}" else setup_user_tool - return $? + rc=$? + if test $rc -ne 0 + then + echo >&2 "error: ${TOOL_MODE}tool.$tool.cmd not set for tool '$tool'" + fi + return $rc fi # Now let the user override the default command for the tool. If @@ -259,6 +264,7 @@ setup_tool () { if ! list_tool_variants | grep -q "^$tool$" then + echo "error: unknown tool variant '$tool'" >&2 return 1 fi @@ -474,7 +480,7 @@ get_merge_tool_path () { merge_tool="$1" if ! valid_tool "$merge_tool" then - echo >&2 "Unknown merge tool $merge_tool" + echo >&2 "Unknown $TOOL_MODE tool $merge_tool" exit 1 fi if diff_mode @@ -54,7 +54,7 @@ import time import zipfile import zlib -# On python2.7 where raw_input() and input() are both availble, +# On python2.7 where raw_input() and input() are both available, # we want raw_input's semantics, but aliased to input for python3 # compatibility # support basestring in python3 @@ -1804,7 +1804,7 @@ class P4Submit(Command, P4UserMap): status from the script will abort the process. The purpose of the hook is to edit the message file in place, and it is not - supressed by the `--no-verify` option. This hook is called even if + suppressed by the `--no-verify` option. This hook is called even if `--prepare-p4-only` is set. The `p4-changelist` hook is executed after the changelist message has been diff --git a/git-send-email.perl b/git-send-email.perl index 72044e5ef3..c4d12bebc8 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -16,7 +16,7 @@ # and second line is the subject of the message. # -use 5.008001; +require v5.26; use strict; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); use Getopt::Long; @@ -31,6 +31,7 @@ sub usage { git send-email [<options>] <file|directory> git send-email [<options>] <format-patch options> git send-email --dump-aliases +git send-email --translate-aliases Composing: --from <str> * Email From: @@ -46,6 +47,8 @@ git send-email --dump-aliases --compose-encoding <str> * Encoding to assume for introduction. --8bit-encoding <str> * Encoding to assume 8bit mails if undeclared --transfer-encoding <str> * Transfer encoding to use (quoted-printable, 8bit, base64) + --[no-]mailmap * Use mailmap file to map all email addresses to canonical + real names and email addresses. Sending: --envelope-sender <str> * Email envelope sender. @@ -99,6 +102,10 @@ git send-email --dump-aliases Information: --dump-aliases * Dump configured aliases and exit. + --translate-aliases * Translate aliases read from standard + input according to the configured email + alias file(s), outputting the result to + standard output. EOT exit(1); @@ -212,6 +219,7 @@ my $format_patch; my $compose_filename; my $force = 0; my $dump_aliases = 0; +my $translate_aliases = 0; # Variables to prevent short format-patch options from being captured # as abbreviated send-email options @@ -272,12 +280,14 @@ my (@suppress_cc); my ($auto_8bit_encoding); my ($compose_encoding); my ($sendmail_cmd); +my ($mailmap_file, $mailmap_blob); # Variables with corresponding config settings & hardcoded defaults my ($debug_net_smtp) = 0; # Net::SMTP, see send_message() my $thread = 1; my $chain_reply_to = 0; my $use_xmailer = 1; my $validate = 1; +my $mailmap = 0; my $target_xfer_encoding = 'auto'; my $forbid_sendmail_variables = 1; @@ -294,6 +304,7 @@ my %config_bool_settings = ( "annotate" => \$annotate, "xmailer" => \$use_xmailer, "forbidsendmailvariables" => \$forbid_sendmail_variables, + "mailmap" => \$mailmap, ); my %config_settings = ( @@ -327,6 +338,8 @@ my %config_settings = ( my %config_path_settings = ( "aliasesfile" => \@alias_files, "smtpsslcertpath" => \$smtp_ssl_cert_path, + "mailmap.file" => \$mailmap_file, + "mailmap.blob" => \$mailmap_blob, ); # Handle Uncouth Termination @@ -476,11 +489,14 @@ my $git_completion_helper; my %dump_aliases_options = ( "h" => \$help, "dump-aliases" => \$dump_aliases, + "translate-aliases" => \$translate_aliases, ); $rc = GetOptions(%dump_aliases_options); usage() unless $rc; die __("--dump-aliases incompatible with other options\n") - if !$help and $dump_aliases and @ARGV; + if !$help and ($dump_aliases or $translate_aliases) and @ARGV; +die __("--dump-aliases and --translate-aliases are mutually exclusive\n") + if !$help and $dump_aliases and $translate_aliases; my %options = ( "sender|from=s" => \$sender, "in-reply-to=s" => \$initial_in_reply_to, @@ -524,6 +540,8 @@ my %options = ( "thread!" => \$thread, "validate!" => \$validate, "transfer-encoding=s" => \$target_xfer_encoding, + "mailmap!" => \$mailmap, + "use-mailmap!" => \$mailmap, "format-patch!" => \$format_patch, "8bit-encoding=s" => \$auto_8bit_encoding, "compose-encoding=s" => \$compose_encoding, @@ -724,6 +742,16 @@ if ($dump_aliases) { exit(0); } +if ($translate_aliases) { + while (<STDIN>) { + my @addr_list = parse_address_line($_); + @addr_list = expand_aliases(@addr_list); + @addr_list = sanitize_address_list(@addr_list); + print "$_\n" for @addr_list; + } + exit(0); +} + # is_format_patch_arg($f) returns 0 if $f names a patch, or 1 if # $f is a revision list specification to be passed to format-patch. sub is_format_patch_arg { @@ -1085,6 +1113,16 @@ if ($compose && $compose > 0) { our ($message_id, %mail, $subject, $in_reply_to, $references, $message, $needs_confirm, $message_num, $ask_default); +sub mailmap_address_list { + return @_ unless @_ and $mailmap; + my @options = (); + push(@options, "--mailmap-file=$mailmap_file") if $mailmap_file; + push(@options, "--mailmap-blob=$mailmap_blob") if $mailmap_blob; + my @addr_list = Git::command('check-mailmap', @options, @_); + s/^<(.*)>$/$1/ for @addr_list; + return @addr_list; +} + sub extract_valid_address { my $address = shift; my $local_part_regexp = qr/[^<>"\s@]+/; @@ -1294,6 +1332,7 @@ sub process_address_list { @addr_list = expand_aliases(@addr_list); @addr_list = sanitize_address_list(@addr_list); @addr_list = validate_address_list(@addr_list); + @addr_list = mailmap_address_list(@addr_list); return @addr_list; } diff --git a/git-submodule.sh b/git-submodule.sh index 7f9582d923..03c5a220a2 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -94,6 +94,14 @@ cmd_add() --reference=*) reference_path="${1#--reference=}" ;; + --ref-format) + case "$2" in '') usage ;; esac + ref_format="--ref-format=$2" + shift + ;; + --ref-format=*) + ref_format="$1" + ;; --dissociate) dissociate=1 ;; @@ -129,7 +137,18 @@ cmd_add() usage fi - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper add ${quiet:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper add \ + ${quiet:+--quiet} \ + ${force:+--force} \ + ${progress:+"--progress"} \ + ${branch:+--branch "$branch"} \ + ${reference_path:+--reference "$reference_path"} \ + ${ref_format:+"$ref_format"} \ + ${dissociate:+--dissociate} \ + ${custom_name:+--name "$custom_name"} \ + ${depth:+"$depth"} \ + -- \ + "$@" } # @@ -160,7 +179,11 @@ cmd_foreach() shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach ${quiet:+--quiet} ${recursive:+--recursive} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach \ + ${quiet:+--quiet} \ + ${recursive:+--recursive} \ + -- \ + "$@" } # @@ -191,7 +214,10 @@ cmd_init() shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${quiet:+--quiet} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init \ + ${quiet:+--quiet} \ + -- \ + "$@" } # @@ -227,7 +253,12 @@ cmd_deinit() shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${quiet:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \ + ${quiet:+--quiet} \ + ${force:+--force} \ + ${deinit_all:+--all} \ + -- \ + "$@" } # @@ -268,6 +299,14 @@ cmd_update() -r|--rebase) rebase=1 ;; + --ref-format) + case "$2" in '') usage ;; esac + ref_format="--ref-format=$2" + shift + ;; + --ref-format=*) + ref_format="$1" + ;; --reference) case "$2" in '') usage ;; esac reference="--reference=$2" @@ -349,6 +388,7 @@ cmd_update() ${rebase:+--rebase} \ ${merge:+--merge} \ ${checkout:+--checkout} \ + ${ref_format:+"$ref_format"} \ ${reference:+"$reference"} \ ${dissociate:+"--dissociate"} \ ${depth:+"$depth"} \ @@ -399,7 +439,12 @@ cmd_set_branch() { shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch ${quiet:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch \ + ${quiet:+--quiet} \ + ${branch:+--branch "$branch"} \ + ${default:+--default} \ + -- \ + "$@" } # @@ -428,7 +473,10 @@ cmd_set_url() { shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url ${quiet:+--quiet} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url \ + ${quiet:+--quiet} \ + -- \ + "$@" } # @@ -480,7 +528,13 @@ cmd_summary() { shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary ${files:+--files} ${cached:+--cached} ${for_status:+--for-status} ${summary_limit:+-n $summary_limit} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary \ + ${files:+--files} \ + ${cached:+--cached} \ + ${for_status:+--for-status} \ + ${summary_limit:+-n $summary_limit} \ + -- \ + "$@" } # # List all submodules, prefixed with: @@ -521,8 +575,14 @@ cmd_status() shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status ${quiet:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status \ + ${quiet:+--quiet} \ + ${cached:+--cached} \ + ${recursive:+--recursive} \ + -- \ + "$@" } + # # Sync remote urls for submodules # This makes the value for remote.$remote.url match the value @@ -554,7 +614,11 @@ cmd_sync() esac done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync ${quiet:+--quiet} ${recursive:+--recursive} -- "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync \ + ${quiet:+--quiet} \ + ${recursive:+--recursive} \ + -- \ + "$@" } cmd_absorbgitdirs() diff --git a/git-svn.perl b/git-svn.perl index b0d0a50984..9c7c629932 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1,7 +1,7 @@ #!/usr/bin/perl # Copyright (C) 2006, Eric Wong <normalperson@yhbt.net> # License: GPL v2 or later -use 5.008001; +require v5.26; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); use strict; use vars qw/ $AUTHOR $VERSION @@ -219,11 +219,11 @@ my %cmd = ( "Set an SVN repository to a git tree-ish", { 'stdin' => \$_stdin, %cmt_opts, %fc_opts, } ], 'create-ignore' => [ \&cmd_create_ignore, - 'Create a .gitignore per svn:ignore', + "Create a .gitignore per directory with SVN ignore properties", { 'revision|r=i' => \$_revision } ], 'mkdirs' => [ \&cmd_mkdirs , - "recreate empty directories after a checkout", + "Recreate empty directories after a checkout", { 'revision|r=i' => \$_revision } ], 'propget' => [ \&cmd_propget, 'Print the value of a property on a file or directory', @@ -234,7 +234,7 @@ my %cmd = ( 'proplist' => [ \&cmd_proplist, 'List all properties of a file or directory', { 'revision|r=i' => \$_revision } ], - 'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings", + 'show-ignore' => [ \&cmd_show_ignore, "Show .gitignore patterns from SVN ignore properties", { 'revision|r=i' => \$_revision } ], 'show-externals' => [ \&cmd_show_externals, "Show svn:externals listings", @@ -1279,12 +1279,20 @@ sub cmd_show_ignore { $gs->prop_walk($gs->path, $r, sub { my ($gs, $path, $props) = @_; print STDOUT "\n# $path\n"; - my $s = $props->{'svn:ignore'} or return; - $s =~ s/[\r\n]+/\n/g; - $s =~ s/^\n+//; - chomp $s; - $s =~ s#^#$path#gm; - print STDOUT "$s\n"; + if (my $s = $props->{'svn:ignore'}) { + $s =~ s/[\r\n]+/\n/g; + $s =~ s/^\n+//; + chomp $s; + $s =~ s#^#$path#gm; + print STDOUT "$s\n"; + } + if (my $s = $props->{'svn:global-ignores'}) { + $s =~ s/[\r\n]+/\n/g; + $s =~ s/^\n+//; + chomp $s; + $s =~ s#^#$path**/#gm; + print STDOUT "$s\n"; + } }); } @@ -1315,16 +1323,25 @@ sub cmd_create_ignore { # which git won't track mkpath([$path]) unless -d $path; my $ignore = $path . '.gitignore'; - my $s = $props->{'svn:ignore'} or return; open(GITIGNORE, '>', $ignore) or fatal("Failed to open `$ignore' for writing: $!"); - $s =~ s/[\r\n]+/\n/g; - $s =~ s/^\n+//; - chomp $s; - # Prefix all patterns so that the ignore doesn't apply - # to sub-directories. - $s =~ s#^#/#gm; - print GITIGNORE "$s\n"; + if (my $s = $props->{'svn:ignore'}) { + $s =~ s/[\r\n]+/\n/g; + $s =~ s/^\n+//; + chomp $s; + # Prefix all patterns so that the ignore doesn't apply + # to sub-directories. + $s =~ s#^#/#gm; + print GITIGNORE "$s\n"; + } + if (my $s = $props->{'svn:global-ignores'}) { + $s =~ s/[\r\n]+/\n/g; + $s =~ s/^\n+//; + chomp $s; + # Global ignores apply to sub-directories, so they are + # not prefixed. + print GITIGNORE "$s\n"; + } close(GITIGNORE) or fatal("Failed to close `$ignore': $!"); command_noisy('add', '-f', $ignore); @@ -31,7 +31,7 @@ struct cmd_struct { const char *cmd; - int (*fn)(int, const char **, const char *); + int (*fn)(int, const char **, const char *, struct repository *); unsigned int option; }; @@ -143,6 +143,13 @@ void setup_auto_pager(const char *cmd, int def) commit_pager_choice(); } +static void print_system_path(const char *path) +{ + char *s_path = system_path(path); + puts(s_path); + free(s_path); +} + static int handle_options(const char ***argv, int *argc, int *envchanged) { const char **orig_argv = *argv; @@ -173,15 +180,15 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) exit(0); } } else if (!strcmp(cmd, "--html-path")) { - puts(system_path(GIT_HTML_PATH)); + print_system_path(GIT_HTML_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "--man-path")) { - puts(system_path(GIT_MAN_PATH)); + print_system_path(GIT_MAN_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "--info-path")) { - puts(system_path(GIT_INFO_PATH)); + print_system_path(GIT_INFO_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { @@ -355,7 +362,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) return (*argv) - orig_argv; } -static int handle_alias(int *argcp, const char ***argv) +static int handle_alias(struct strvec *args) { int envchanged = 0, ret = 0, saved_errno = errno; int count, option_count; @@ -363,10 +370,10 @@ static int handle_alias(int *argcp, const char ***argv) const char *alias_command; char *alias_string; - alias_command = (*argv)[0]; + alias_command = args->v[0]; alias_string = alias_lookup(alias_command); if (alias_string) { - if (*argcp > 1 && !strcmp((*argv)[1], "-h")) + if (args->nr > 1 && !strcmp(args->v[1], "-h")) fprintf_ln(stderr, _("'%s' is aliased to '%s'"), alias_command, alias_string); if (alias_string[0] == '!') { @@ -383,7 +390,7 @@ static int handle_alias(int *argcp, const char ***argv) child.wait_after_clean = 1; child.trace2_child_class = "shell_alias"; strvec_push(&child.args, alias_string + 1); - strvec_pushv(&child.args, (*argv) + 1); + strvec_pushv(&child.args, args->v + 1); trace2_cmd_alias(alias_command, child.args.v); trace2_cmd_name("_run_shell_alias_"); @@ -416,15 +423,13 @@ static int handle_alias(int *argcp, const char ***argv) trace_argv_printf(new_argv, "trace: alias expansion: %s =>", alias_command); - - REALLOC_ARRAY(new_argv, count + *argcp); - /* insert after command name */ - COPY_ARRAY(new_argv + count, *argv + 1, *argcp); - trace2_cmd_alias(alias_command, new_argv); - *argv = new_argv; - *argcp += count - 1; + /* Replace the alias with the new arguments. */ + strvec_splice(args, 0, 1, new_argv, count); + + free(alias_string); + free(new_argv); ret = 1; } @@ -434,9 +439,10 @@ static int handle_alias(int *argcp, const char ***argv) return ret; } -static int run_builtin(struct cmd_struct *p, int argc, const char **argv) +static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct repository *repo) { int status, help; + int no_repo = 1; struct stat st; const char *prefix; int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY)); @@ -448,9 +454,9 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) if (run_setup & RUN_SETUP) { prefix = setup_git_directory(); + no_repo = 0; } else if (run_setup & RUN_SETUP_GENTLY) { - int nongit_ok; - prefix = setup_git_directory_gently(&nongit_ok); + prefix = setup_git_directory_gently(&no_repo); } else { prefix = NULL; } @@ -472,9 +478,9 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) trace_argv_printf(argv, "trace: built-in: git"); trace2_cmd_name(p->cmd); - validate_cache_entries(the_repository->index); - status = p->fn(argc, argv, prefix); - validate_cache_entries(the_repository->index); + validate_cache_entries(repo->index); + status = p->fn(argc, argv, prefix, no_repo ? NULL : repo); + validate_cache_entries(repo->index); if (status) return status; @@ -690,47 +696,57 @@ void load_builtin_commands(const char *prefix, struct cmdnames *cmds) } #ifdef STRIP_EXTENSION -static void strip_extension(const char **argv) +static void strip_extension(struct strvec *args) { size_t len; - if (strip_suffix(argv[0], STRIP_EXTENSION, &len)) - argv[0] = xmemdupz(argv[0], len); + if (strip_suffix(args->v[0], STRIP_EXTENSION, &len)) { + char *stripped = xmemdupz(args->v[0], len); + strvec_replace(args, 0, stripped); + free(stripped); + } } #else #define strip_extension(cmd) #endif -static void handle_builtin(int argc, const char **argv) +static void handle_builtin(struct strvec *args) { - struct strvec args = STRVEC_INIT; const char *cmd; struct cmd_struct *builtin; - strip_extension(argv); - cmd = argv[0]; + strip_extension(args); + cmd = args->v[0]; /* Turn "git cmd --help" into "git help --exclude-guides cmd" */ - if (argc > 1 && !strcmp(argv[1], "--help")) { - int i; + if (args->nr > 1 && !strcmp(args->v[1], "--help")) { + const char *exclude_guides_arg[] = { "--exclude-guides" }; + + strvec_replace(args, 1, args->v[0]); + strvec_replace(args, 0, "help"); + cmd = "help"; + strvec_splice(args, 2, 0, exclude_guides_arg, + ARRAY_SIZE(exclude_guides_arg)); + } - argv[1] = argv[0]; - argv[0] = cmd = "help"; + builtin = get_builtin(cmd); + if (builtin) { + const char **argv_copy = NULL; + int ret; - for (i = 0; i < argc; i++) { - strvec_push(&args, argv[i]); - if (!i) - strvec_push(&args, "--exclude-guides"); - } + /* + * `run_builtin()` will modify the argv array, so we need to + * create a shallow copy such that we can free all of its + * strings. + */ + if (args->nr) + DUP_ARRAY(argv_copy, args->v, args->nr + 1); - argc++; - argv = args.v; + ret = run_builtin(builtin, args->nr, argv_copy, the_repository); + strvec_clear(args); + free(argv_copy); + exit(ret); } - - builtin = get_builtin(cmd); - if (builtin) - exit(run_builtin(builtin, argc, argv)); - strvec_clear(&args); } static void execv_dashed_external(const char **argv) @@ -776,10 +792,10 @@ static void execv_dashed_external(const char **argv) exit(128); } -static int run_argv(int *argcp, const char ***argv) +static int run_argv(struct strvec *args) { int done_alias = 0; - struct string_list cmd_list = STRING_LIST_INIT_NODUP; + struct string_list cmd_list = STRING_LIST_INIT_DUP; struct string_list_item *seen; while (1) { @@ -793,8 +809,8 @@ static int run_argv(int *argcp, const char ***argv) * process. */ if (!done_alias) - handle_builtin(*argcp, *argv); - else if (get_builtin(**argv)) { + handle_builtin(args); + else if (get_builtin(args->v[0])) { struct child_process cmd = CHILD_PROCESS_INIT; int i; @@ -810,8 +826,8 @@ static int run_argv(int *argcp, const char ***argv) commit_pager_choice(); strvec_push(&cmd.args, "git"); - for (i = 0; i < *argcp; i++) - strvec_push(&cmd.args, (*argv)[i]); + for (i = 0; i < args->nr; i++) + strvec_push(&cmd.args, args->v[i]); trace_argv_printf(cmd.args.v, "trace: exec:"); @@ -826,13 +842,13 @@ static int run_argv(int *argcp, const char ***argv) i = run_command(&cmd); if (i >= 0 || errno != ENOENT) exit(i); - die("could not execute builtin %s", **argv); + die("could not execute builtin %s", args->v[0]); } /* .. then try the external ones */ - execv_dashed_external(*argv); + execv_dashed_external(args->v); - seen = unsorted_string_list_lookup(&cmd_list, *argv[0]); + seen = unsorted_string_list_lookup(&cmd_list, args->v[0]); if (seen) { int i; struct strbuf sb = STRBUF_INIT; @@ -849,14 +865,14 @@ static int run_argv(int *argcp, const char ***argv) " not terminate:%s"), cmd_list.items[0].string, sb.buf); } - string_list_append(&cmd_list, *argv[0]); + string_list_append(&cmd_list, args->v[0]); /* * It could be an alias -- this works around the insanity * of overriding "git log" with "git show" by having * alias.log = show */ - if (!handle_alias(argcp, argv)) + if (!handle_alias(args)) break; done_alias = 1; } @@ -868,6 +884,7 @@ static int run_argv(int *argcp, const char ***argv) int cmd_main(int argc, const char **argv) { + struct strvec args = STRVEC_INIT; const char *cmd; int done_help = 0; @@ -893,8 +910,10 @@ int cmd_main(int argc, const char **argv) * that one cannot handle it. */ if (skip_prefix(cmd, "git-", &cmd)) { - argv[0] = cmd; - handle_builtin(argc, argv); + strvec_push(&args, cmd); + strvec_pushv(&args, argv + 1); + handle_builtin(&args); + strvec_clear(&args); die(_("cannot handle %s as a builtin"), cmd); } @@ -927,25 +946,34 @@ int cmd_main(int argc, const char **argv) */ setup_path(); + for (size_t i = 0; i < argc; i++) + strvec_push(&args, argv[i]); + while (1) { - int was_alias = run_argv(&argc, &argv); + int was_alias = run_argv(&args); if (errno != ENOENT) break; if (was_alias) { fprintf(stderr, _("expansion of alias '%s' failed; " "'%s' is not a git command\n"), - cmd, argv[0]); + cmd, args.v[0]); + strvec_clear(&args); exit(1); } if (!done_help) { - cmd = argv[0] = help_unknown_cmd(cmd); + char *assumed = help_unknown_cmd(cmd); + strvec_replace(&args, 0, assumed); + free(assumed); + cmd = args.v[0]; done_help = 1; - } else + } else { break; + } } fprintf(stderr, _("failed to run command '%s': %s\n"), cmd, strerror(errno)); + strvec_clear(&args); return 1; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b09a8d0523..b50a1444b2 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -7,7 +7,7 @@ # # This program is licensed under the GPLv2 -use 5.008001; +require v5.26; use strict; use warnings; # handle ACL in file access tests @@ -1188,7 +1188,7 @@ sub evaluate_and_validate_params { if ($search_use_regexp) { $search_regexp = $searchtext; if (!eval { qr/$search_regexp/; 1; }) { - (my $error = $@) =~ s/ at \S+ line \d+.*\n?//; + my $error = $@ =~ s/ at \S+ line \d+.*\n?//r; die_error(400, "Invalid search regexp '$search_regexp'", esc_html($error)); } @@ -2094,7 +2094,7 @@ sub format_log_line_html { ( # The output of "git describe", e.g. v2.10.0-297-gf6727b0 # or hadoop-20160921-113441-20-g094fb7d - (?<!-) # see strbuf_check_tag_ref(). Tags can't start with - + (?<!-) # see check_tag_ref(). Tags can't start with - [A-Za-z0-9.-]+ (?!\.) # refs can't end with ".", see check_refname_format() -g$regex @@ -2700,7 +2700,7 @@ sub git_cmd { # Try to avoid using this function wherever possible. sub quote_command { return join(' ', - map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ); + map { my $a = $_ =~ s/(['!])/'\\$1'/gr; "'$a'" } @_ ); } # get HEAD ref of given project as hash diff --git a/gpg-interface.c b/gpg-interface.c index 5c824aeb25..07335987a6 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "commit.h" #include "config.h" @@ -43,8 +45,8 @@ struct gpg_format { size_t signature_size); int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature, const char *signing_key); - const char *(*get_default_key)(void); - const char *(*get_key_id)(void); + char *(*get_default_key)(void); + char *(*get_key_id)(void); }; static const char *openpgp_verify_args[] = { @@ -84,9 +86,9 @@ static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature, static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature, const char *signing_key); -static const char *get_default_ssh_signing_key(void); +static char *get_default_ssh_signing_key(void); -static const char *get_ssh_key_id(void); +static char *get_ssh_key_id(void); static struct gpg_format gpg_format[] = { { @@ -398,7 +400,7 @@ static void parse_ssh_output(struct signature_check *sigc) * Note that "PRINCIPAL" can contain whitespace, "RSA" and * "SHA256" part could be a different token that names of * the algorithms used, and "FINGERPRINT" is a hexadecimal - * string. By finding the last occurence of " with ", we can + * string. By finding the last occurrence of " with ", we can * reliably parse out the PRINCIPAL. */ sigc->result = 'B'; @@ -845,7 +847,7 @@ static char *get_ssh_key_fingerprint(const char *signing_key) } /* Returns the first public key from an ssh-agent to use for signing */ -static const char *get_default_ssh_signing_key(void) +static char *get_default_ssh_signing_key(void) { struct child_process ssh_default_key = CHILD_PROCESS_INIT; int ret = -1; @@ -897,12 +899,16 @@ static const char *get_default_ssh_signing_key(void) return default_key; } -static const char *get_ssh_key_id(void) { - return get_ssh_key_fingerprint(get_signing_key()); +static char *get_ssh_key_id(void) +{ + char *signing_key = get_signing_key(); + char *key_id = get_ssh_key_fingerprint(signing_key); + free(signing_key); + return key_id; } /* Returns a textual but unique representation of the signing key */ -const char *get_signing_key_id(void) +char *get_signing_key_id(void) { gpg_interface_lazy_init(); @@ -914,17 +920,17 @@ const char *get_signing_key_id(void) return get_signing_key(); } -const char *get_signing_key(void) +char *get_signing_key(void) { gpg_interface_lazy_init(); if (configured_signing_key) - return configured_signing_key; + return xstrdup(configured_signing_key); if (use_format->get_default_key) { return use_format->get_default_key(); } - return git_committer_info(IDENT_STRICT | IDENT_NO_DATE); + return xstrdup(git_committer_info(IDENT_STRICT | IDENT_NO_DATE)); } const char *gpg_trust_level_to_str(enum signature_trust_level level) diff --git a/gpg-interface.h b/gpg-interface.h index 7cd98161f7..e09f12e8d0 100644 --- a/gpg-interface.h +++ b/gpg-interface.h @@ -80,13 +80,13 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *gpg_trust_level_to_str(enum signature_trust_level level); void set_signing_key(const char *); -const char *get_signing_key(void); +char *get_signing_key(void); /* * Returns a textual unique representation of the signing key in use * Either a GPG KeyID or a SSH Key Fingerprint */ -const char *get_signing_key_id(void); +char *get_signing_key_id(void); int check_signature(struct signature_check *sigc, const char *signature, size_t slen); void print_signature_buffer(const struct signature_check *sigc, @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "gettext.h" #include "config.h" @@ -74,10 +76,7 @@ static void graph_show_line_prefix(const struct diff_options *diffopt) if (!diffopt || !diffopt->line_prefix) return; - fwrite(diffopt->line_prefix, - sizeof(char), - diffopt->line_prefix_length, - diffopt->file); + fputs(diffopt->line_prefix, diffopt->file); } static const char **column_colors; @@ -310,22 +309,28 @@ struct git_graph { * stored as an index into the array column_colors. */ unsigned short default_column_color; + + /* + * Scratch buffer for generating prefixes to be used with + * diff_output_prefix_callback(). + */ + struct strbuf prefix_buf; }; -static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void *data) +static const char *diff_output_prefix_callback(struct diff_options *opt, void *data) { struct git_graph *graph = data; - static struct strbuf msgbuf = STRBUF_INIT; assert(opt); - strbuf_reset(&msgbuf); + if (!graph) + return opt->line_prefix; + + strbuf_reset(&graph->prefix_buf); if (opt->line_prefix) - strbuf_add(&msgbuf, opt->line_prefix, - opt->line_prefix_length); - if (graph) - graph_padding_line(graph, &msgbuf); - return &msgbuf; + strbuf_addstr(&graph->prefix_buf, opt->line_prefix); + graph_padding_line(graph, &graph->prefix_buf); + return graph->prefix_buf.buf; } static const struct diff_options *default_diffopt; @@ -395,6 +400,7 @@ struct git_graph *graph_init(struct rev_info *opt) * The diff output prefix callback, with this we can make * all the diff output to align with the graph lines. */ + strbuf_init(&graph->prefix_buf, 0); opt->diffopt.output_prefix = diff_output_prefix_callback; opt->diffopt.output_prefix_data = graph; @@ -410,6 +416,7 @@ void graph_clear(struct git_graph *graph) free(graph->new_columns); free(graph->mapping); free(graph->old_mapping); + strbuf_release(&graph->prefix_buf); free(graph); } @@ -245,7 +245,7 @@ static int is_fixed(const char *s, size_t len) #ifdef USE_LIBPCRE2 #define GREP_PCRE2_DEBUG_MALLOC 0 -static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data) +static void *pcre2_malloc(PCRE2_SIZE size, void *memory_data UNUSED) { void *pointer = malloc(size); #if GREP_PCRE2_DEBUG_MALLOC @@ -255,7 +255,7 @@ static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data) return pointer; } -static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data) +static void pcre2_free(void *pointer, void *memory_data UNUSED) { #if GREP_PCRE2_DEBUG_MALLOC static int count = 1; @@ -756,6 +756,7 @@ static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y assert(x->node == GREP_NODE_OR); if (x->u.binary.right && x->u.binary.right->node == GREP_NODE_TRUE) { + free(x->u.binary.right); x->u.binary.right = y; break; } @@ -843,11 +844,11 @@ static void free_grep_pat(struct grep_pat *pattern) free_pcre2_pattern(p); else regfree(&p->regexp); - free(p->pattern); break; default: break; } + free(p->pattern); free(p); } } @@ -906,15 +907,17 @@ static int patmatch(struct grep_pat *p, const char *line, const char *eol, regmatch_t *match, int eflags) { - int hit; - if (p->pcre2_pattern) - hit = !pcre2match(p, line, eol, match, eflags); - else - hit = !regexec_buf(&p->regexp, line, eol - line, 1, match, - eflags); + return !pcre2match(p, line, eol, match, eflags); - return hit; + switch (regexec_buf(&p->regexp, line, eol - line, 1, match, eflags)) { + case 0: + return 1; + case REG_NOMATCH: + return 0; + default: + return -1; + } } static void strip_timestamp(const char *bol, const char **eol_p) @@ -952,6 +955,8 @@ static int headerless_match_one_pattern(struct grep_pat *p, again: hit = patmatch(p, bol, eol, pmatch, eflags); + if (hit < 0) + hit = 0; if (hit && p->word_regexp) { if ((pmatch[0].rm_so < 0) || @@ -1461,6 +1466,8 @@ static int look_ahead(struct grep_opt *opt, regmatch_t m; hit = patmatch(p, bol, bol + *left_p, &m, 0); + if (hit < 0) + return -1; if (!hit || m.rm_so < 0 || m.rm_eo < 0) continue; if (earliest < 0 || m.rm_so < earliest) @@ -1655,9 +1662,13 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle if (try_lookahead && !(last_hit && (show_function || - lno <= last_hit + opt->post_context)) - && look_ahead(opt, &left, &lno, &bol)) - break; + lno <= last_hit + opt->post_context))) { + hit = look_ahead(opt, &left, &lno, &bol); + if (hit < 0) + try_lookahead = 0; + else if (hit) + break; + } eol = end_of_line(bol, &left); if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol)) @@ -1735,7 +1746,8 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle peek_eol = end_of_line(peek_bol, &peek_left); } - if (match_funcname(opt, gs, peek_bol, peek_eol)) + if (peek_bol >= gs->buf + gs->size || + match_funcname(opt, gs, peek_bol, peek_eol)) show_function = 0; } if (show_function || @@ -15,6 +15,36 @@ #include "block-sha1/sha1.h" #endif +#if defined(SHA1_APPLE_UNSAFE) +# include <CommonCrypto/CommonDigest.h> +# define platform_SHA_CTX_unsafe CC_SHA1_CTX +# define platform_SHA1_Init_unsafe CC_SHA1_Init +# define platform_SHA1_Update_unsafe CC_SHA1_Update +# define platform_SHA1_Final_unsafe CC_SHA1_Final +#elif defined(SHA1_OPENSSL_UNSAFE) +# include <openssl/sha.h> +# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 +# define SHA1_NEEDS_CLONE_HELPER_UNSAFE +# include "sha1/openssl.h" +# define platform_SHA_CTX_unsafe openssl_SHA1_CTX +# define platform_SHA1_Init_unsafe openssl_SHA1_Init +# define platform_SHA1_Clone_unsafe openssl_SHA1_Clone +# define platform_SHA1_Update_unsafe openssl_SHA1_Update +# define platform_SHA1_Final_unsafe openssl_SHA1_Final +# else +# define platform_SHA_CTX_unsafe SHA_CTX +# define platform_SHA1_Init_unsafe SHA1_Init +# define platform_SHA1_Update_unsafe SHA1_Update +# define platform_SHA1_Final_unsafe SHA1_Final +# endif +#elif defined(SHA1_BLK_UNSAFE) +# include "block-sha1/sha1.h" +# define platform_SHA_CTX_unsafe blk_SHA_CTX +# define platform_SHA1_Init_unsafe blk_SHA1_Init +# define platform_SHA1_Update_unsafe blk_SHA1_Update +# define platform_SHA1_Final_unsafe blk_SHA1_Final +#endif + #if defined(SHA256_NETTLE) #include "sha256/nettle.h" #elif defined(SHA256_GCRYPT) @@ -44,14 +74,35 @@ #define platform_SHA1_Final SHA1_Final #endif +#ifndef platform_SHA_CTX_unsafe +# define platform_SHA_CTX_unsafe platform_SHA_CTX +# define platform_SHA1_Init_unsafe platform_SHA1_Init +# define platform_SHA1_Update_unsafe platform_SHA1_Update +# define platform_SHA1_Final_unsafe platform_SHA1_Final +# ifdef platform_SHA1_Clone +# define platform_SHA1_Clone_unsafe platform_SHA1_Clone +# endif +# ifdef SHA1_NEEDS_CLONE_HELPER +# define SHA1_NEEDS_CLONE_HELPER_UNSAFE +# endif +#endif + #define git_SHA_CTX platform_SHA_CTX #define git_SHA1_Init platform_SHA1_Init #define git_SHA1_Update platform_SHA1_Update #define git_SHA1_Final platform_SHA1_Final +#define git_SHA_CTX_unsafe platform_SHA_CTX_unsafe +#define git_SHA1_Init_unsafe platform_SHA1_Init_unsafe +#define git_SHA1_Update_unsafe platform_SHA1_Update_unsafe +#define git_SHA1_Final_unsafe platform_SHA1_Final_unsafe + #ifdef platform_SHA1_Clone #define git_SHA1_Clone platform_SHA1_Clone #endif +#ifdef platform_SHA1_Clone_unsafe +# define git_SHA1_Clone_unsafe platform_SHA1_Clone_unsafe +#endif #ifndef platform_SHA256_CTX #define platform_SHA256_CTX SHA256_CTX @@ -81,6 +132,13 @@ static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src) memcpy(dst, src, sizeof(*dst)); } #endif +#ifndef SHA1_NEEDS_CLONE_HELPER_UNSAFE +static inline void git_SHA1_Clone_unsafe(git_SHA_CTX_unsafe *dst, + const git_SHA_CTX_unsafe *src) +{ + memcpy(dst, src, sizeof(*dst)); +} +#endif #ifndef SHA256_NEEDS_CLONE_HELPER static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src) @@ -178,6 +236,8 @@ enum get_oid_result { /* A suitably aligned type for stack allocations of hash contexts. */ union git_hash_ctx { git_SHA_CTX sha1; + git_SHA_CTX_unsafe sha1_unsafe; + git_SHA256_CTX sha256; }; typedef union git_hash_ctx git_hash_ctx; @@ -222,6 +282,21 @@ struct git_hash_algo { /* The hash finalization function for object IDs. */ git_hash_final_oid_fn final_oid_fn; + /* The non-cryptographic hash initialization function. */ + git_hash_init_fn unsafe_init_fn; + + /* The non-cryptographic hash context cloning function. */ + git_hash_clone_fn unsafe_clone_fn; + + /* The non-cryptographic hash update function. */ + git_hash_update_fn unsafe_update_fn; + + /* The non-cryptographic hash finalization function. */ + git_hash_final_fn unsafe_final_fn; + + /* The non-cryptographic hash finalization function. */ + git_hash_final_oid_fn unsafe_final_oid_fn; + /* The OID of the empty tree. */ const struct object_id *empty_tree; @@ -16,6 +16,7 @@ #include "parse-options.h" #include "prompt.h" #include "fsmonitor-ipc.h" +#include "repository.h" #ifndef NO_CURL #include "git-curl-compat.h" /* For LIBCURL_VERSION only */ @@ -545,8 +546,10 @@ int is_in_cmdlist(struct cmdnames *c, const char *s) return 0; } -static int autocorrect; -static struct cmdnames aliases; +struct help_unknown_cmd_config { + int autocorrect; + struct cmdnames aliases; +}; #define AUTOCORRECT_PROMPT (-3) #define AUTOCORRECT_NEVER (-2) @@ -554,28 +557,29 @@ static struct cmdnames aliases; static int git_unknown_cmd_config(const char *var, const char *value, const struct config_context *ctx, - void *cb UNUSED) + void *cb) { + struct help_unknown_cmd_config *cfg = cb; const char *p; if (!strcmp(var, "help.autocorrect")) { if (!value) return config_error_nonbool(var); if (!strcmp(value, "never")) { - autocorrect = AUTOCORRECT_NEVER; + cfg->autocorrect = AUTOCORRECT_NEVER; } else if (!strcmp(value, "immediate")) { - autocorrect = AUTOCORRECT_IMMEDIATELY; + cfg->autocorrect = AUTOCORRECT_IMMEDIATELY; } else if (!strcmp(value, "prompt")) { - autocorrect = AUTOCORRECT_PROMPT; + cfg->autocorrect = AUTOCORRECT_PROMPT; } else { int v = git_config_int(var, value, ctx->kvi); - autocorrect = (v < 0) + cfg->autocorrect = (v < 0) ? AUTOCORRECT_IMMEDIATELY : v; } } /* Also use aliases for command lookup */ if (skip_prefix(var, "alias.", &p)) - add_cmdname(&aliases, p, strlen(p)); + add_cmdname(&cfg->aliases, p, strlen(p)); return 0; } @@ -608,32 +612,30 @@ static const char bad_interpreter_advice[] = N_("'%s' appears to be a git command, but we were not\n" "able to execute it. Maybe git-%s is broken?"); -const char *help_unknown_cmd(const char *cmd) +char *help_unknown_cmd(const char *cmd) { + struct help_unknown_cmd_config cfg = { 0 }; int i, n, best_similarity = 0; - struct cmdnames main_cmds, other_cmds; + struct cmdnames main_cmds = { 0 }; + struct cmdnames other_cmds = { 0 }; struct cmdname_help *common_cmds; - memset(&main_cmds, 0, sizeof(main_cmds)); - memset(&other_cmds, 0, sizeof(other_cmds)); - memset(&aliases, 0, sizeof(aliases)); - - read_early_config(git_unknown_cmd_config, NULL); + read_early_config(the_repository, git_unknown_cmd_config, &cfg); /* * Disable autocorrection prompt in a non-interactive session */ - if ((autocorrect == AUTOCORRECT_PROMPT) && (!isatty(0) || !isatty(2))) - autocorrect = AUTOCORRECT_NEVER; + if ((cfg.autocorrect == AUTOCORRECT_PROMPT) && (!isatty(0) || !isatty(2))) + cfg.autocorrect = AUTOCORRECT_NEVER; - if (autocorrect == AUTOCORRECT_NEVER) { + if (cfg.autocorrect == AUTOCORRECT_NEVER) { fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd); exit(1); } load_command_list("git-", &main_cmds, &other_cmds); - add_cmd_list(&main_cmds, &aliases); + add_cmd_list(&main_cmds, &cfg.aliases); add_cmd_list(&main_cmds, &other_cmds); QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare); uniq(&main_cmds); @@ -692,20 +694,19 @@ const char *help_unknown_cmd(const char *cmd) n++) ; /* still counting */ } - if (autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) { - const char *assumed = main_cmds.names[0]->name; - main_cmds.names[0] = NULL; - cmdnames_release(&main_cmds); + if (cfg.autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) { + char *assumed = xstrdup(main_cmds.names[0]->name); + fprintf_ln(stderr, _("WARNING: You called a Git command named '%s', " "which does not exist."), cmd); - if (autocorrect == AUTOCORRECT_IMMEDIATELY) + if (cfg.autocorrect == AUTOCORRECT_IMMEDIATELY) fprintf_ln(stderr, _("Continuing under the assumption that " "you meant '%s'."), assumed); - else if (autocorrect == AUTOCORRECT_PROMPT) { + else if (cfg.autocorrect == AUTOCORRECT_PROMPT) { char *answer; struct strbuf msg = STRBUF_INIT; strbuf_addf(&msg, _("Run '%s' instead [y/N]? "), assumed); @@ -718,9 +719,13 @@ const char *help_unknown_cmd(const char *cmd) fprintf_ln(stderr, _("Continuing in %0.1f seconds, " "assuming that you meant '%s'."), - (float)autocorrect/10.0, assumed); - sleep_millisec(autocorrect * 100); + (float)cfg.autocorrect/10.0, assumed); + sleep_millisec(cfg.autocorrect * 100); } + + cmdnames_release(&cfg.aliases); + cmdnames_release(&main_cmds); + cmdnames_release(&other_cmds); return assumed; } @@ -775,7 +780,7 @@ void get_version_info(struct strbuf *buf, int show_build_options) } } -int cmd_version(int argc, const char **argv, const char *prefix) +int cmd_version(int argc, const char **argv, const char *prefix, struct repository *repository UNUSED) { struct strbuf buf = STRBUF_INIT; int build_options = 0; @@ -804,7 +809,7 @@ struct similar_ref_cb { struct string_list *similar_refs; }; -static int append_similar_ref(const char *refname, +static int append_similar_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data) { @@ -32,7 +32,7 @@ void list_all_other_cmds(struct string_list *list); void list_cmds_by_category(struct string_list *list, const char *category); void list_cmds_by_config(struct string_list *list); -const char *help_unknown_cmd(const char *cmd); +char *help_unknown_cmd(const char *cmd); void load_command_list(const char *prefix, struct cmdnames *main_cmds, struct cmdnames *other_cmds); @@ -10,14 +10,14 @@ #include "environment.h" #include "setup.h" -const char *find_hook(const char *name) +const char *find_hook(struct repository *r, const char *name) { static struct strbuf path = STRBUF_INIT; int found_hook; strbuf_reset(&path); - strbuf_git_path(&path, "hooks/%s", name); + strbuf_repo_git_path(&path, r, "hooks/%s", name); found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION if (!found_hook) { @@ -39,7 +39,7 @@ const char *find_hook(const char *name) advise(_("The '%s' hook was ignored because " "it's not set as executable.\n" "You can disable this warning with " - "`git config advice.ignoredHook false`."), + "`git config set advice.ignoredHook false`."), path.buf); } } @@ -48,9 +48,9 @@ const char *find_hook(const char *name) return path.buf; } -int hook_exists(const char *name) +int hook_exists(struct repository *r, const char *name) { - return !!find_hook(name); + return !!find_hook(r, name); } static int pick_next_hook(struct child_process *cp, @@ -121,7 +121,8 @@ static void run_hooks_opt_clear(struct run_hooks_opt *options) strvec_clear(&options->args); } -int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options) +int run_hooks_opt(struct repository *r, const char *hook_name, + struct run_hooks_opt *options) { struct strbuf abs_path = STRBUF_INIT; struct hook_cb_data cb_data = { @@ -129,7 +130,7 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options) .hook_name = hook_name, .options = options, }; - const char *const hook_path = find_hook(hook_name); + const char *const hook_path = find_hook(r, hook_name); int ret = 0; const struct run_process_parallel_opts opts = { .tr2_category = "hook", @@ -173,14 +174,14 @@ cleanup: return ret; } -int run_hooks(const char *hook_name) +int run_hooks(struct repository *r, const char *hook_name) { struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; - return run_hooks_opt(hook_name, &opt); + return run_hooks_opt(r, hook_name, &opt); } -int run_hooks_l(const char *hook_name, ...) +int run_hooks_l(struct repository *r, const char *hook_name, ...) { struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; va_list ap; @@ -191,5 +192,5 @@ int run_hooks_l(const char *hook_name, ...) strvec_push(&opt.args, arg); va_end(ap); - return run_hooks_opt(hook_name, &opt); + return run_hooks_opt(r, hook_name, &opt); } @@ -2,6 +2,8 @@ #define HOOK_H #include "strvec.h" +struct repository; + struct run_hooks_opt { /* Environment vars to be set for each hook */ @@ -55,12 +57,12 @@ struct hook_cb_data { * or disabled. Note that this points to static storage that will be * overwritten by further calls to find_hook and run_hook_*. */ -const char *find_hook(const char *name); +const char *find_hook(struct repository *r, const char *name); /** * A boolean version of find_hook() */ -int hook_exists(const char *hookname); +int hook_exists(struct repository *r, const char *hookname); /** * Takes a `hook_name`, resolves it to a path with find_hook(), and @@ -70,13 +72,14 @@ int hook_exists(const char *hookname); * Returns the status code of the run hook, or a negative value on * error(). */ -int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options); +int run_hooks_opt(struct repository *r, const char *hook_name, + struct run_hooks_opt *options); /** * A wrapper for run_hooks_opt() which provides a dummy "struct * run_hooks_opt" initialized with "RUN_HOOKS_OPT_INIT". */ -int run_hooks(const char *hook_name); +int run_hooks(struct repository *r, const char *hook_name); /** * Like run_hooks(), a wrapper for run_hooks_opt(). @@ -87,5 +90,5 @@ int run_hooks(const char *hook_name); * hook. This function behaves like the old run_hook_le() API. */ LAST_ARG_MUST_BE_NULL -int run_hooks_l(const char *hook_name, ...); +int run_hooks_l(struct repository *r, const char *hook_name, ...); #endif diff --git a/http-backend.c b/http-backend.c index 461424972b..73eec4ea3d 100644 --- a/http-backend.c +++ b/http-backend.c @@ -512,7 +512,7 @@ static void run_service(const char **argv, int buffer_input) exit(1); } -static int show_text_ref(const char *name, const struct object_id *oid, +static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { const char *name_nons = strip_namespace(name); @@ -568,7 +568,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED) strbuf_release(&buf); } -static int show_head_ref(const char *refname, const struct object_id *oid, +static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { struct strbuf *buf = cb_data; @@ -601,7 +601,7 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED) static void get_info_packs(struct strbuf *hdr, char *arg UNUSED) { - size_t objdirlen = strlen(get_object_directory()); + size_t objdirlen = strlen(repo_get_object_directory(the_repository)); struct strbuf buf = STRBUF_INIT; struct packed_git *p; size_t cnt = 0; diff --git a/http-fetch.c b/http-fetch.c index d460bb1837..02ab80533f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -106,6 +106,7 @@ int cmd_main(int argc, const char **argv) int nongit; struct object_id packfile_hash; struct strvec index_pack_args = STRVEC_INIT; + int ret; setup_git_directory_gently(&nongit); @@ -157,8 +158,8 @@ int cmd_main(int argc, const char **argv) fetch_single_packfile(&packfile_hash, argv[arg], index_pack_args.v); - - return 0; + ret = 0; + goto out; } if (index_pack_args.nr) @@ -170,7 +171,12 @@ int cmd_main(int argc, const char **argv) commit_id = (char **) &argv[arg++]; commits = 1; } - return fetch_using_walker(argv[arg], get_verbosely, get_recover, - commits, commit_id, write_ref, - commits_on_stdin); + + ret = fetch_using_walker(argv[arg], get_verbosely, get_recover, + commits, commit_id, write_ref, + commits_on_stdin); + +out: + strvec_clear(&index_pack_args); + return ret; } diff --git a/http-push.c b/http-push.c index 7315a694aa..4d24e6b8d4 100644 --- a/http-push.c +++ b/http-push.c @@ -275,7 +275,7 @@ static void start_fetch_loose(struct transfer_request *request) if (!start_active_slot(slot)) { fprintf(stderr, "Unable to start GET request\n"); repo->can_update_info_refs = 0; - release_http_object_request(obj_req); + release_http_object_request(&obj_req); release_request(request); } } @@ -309,7 +309,7 @@ static void start_fetch_packed(struct transfer_request *request) struct transfer_request *check_request = request_queue_head; struct http_pack_request *preq; - target = find_sha1_pack(request->obj->oid.hash, repo->packs); + target = find_oid_pack(&request->obj->oid, repo->packs); if (!target) { fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid)); repo->can_update_info_refs = 0; @@ -375,7 +375,7 @@ static void start_put(struct transfer_request *request) /* Set it up */ git_deflate_init(&stream, zlib_compression_level); size = git_deflate_bound(&stream, len + hdrlen); - strbuf_init(&request->buffer.buf, size); + strbuf_grow(&request->buffer.buf, size); request->buffer.posn = 0; /* Compress it */ @@ -437,9 +437,11 @@ static void start_move(struct transfer_request *request) if (start_active_slot(slot)) { request->slot = slot; request->state = RUN_MOVE; + request->headers = dav_headers; } else { request->state = ABORTED; FREE_AND_NULL(request->url); + curl_slist_free_all(dav_headers); } } @@ -512,6 +514,8 @@ static void release_request(struct transfer_request *request) } free(request->url); + free(request->dest); + strbuf_release(&request->buffer.buf); free(request); } @@ -578,9 +582,10 @@ static void finish_request(struct transfer_request *request) if (obj_req->rename == 0) request->obj->flags |= (LOCAL | REMOTE); + release_http_object_request(&obj_req); + /* Try fetching packed if necessary */ if (request->obj->flags & LOCAL) { - release_http_object_request(obj_req); release_request(request); } else start_fetch_packed(request); @@ -649,12 +654,10 @@ static void add_fetch_request(struct object *obj) return; obj->flags |= FETCHING; - request = xmalloc(sizeof(*request)); + CALLOC_ARRAY(request, 1); request->obj = obj; - request->url = NULL; - request->lock = NULL; - request->headers = NULL; request->state = NEED_FETCH; + strbuf_init(&request->buffer.buf, 0); request->next = request_queue_head; request_queue_head = request; @@ -678,19 +681,18 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) get_remote_object_list(obj->oid.hash[0]); if (obj->flags & (REMOTE | PUSHING)) return 0; - target = find_sha1_pack(obj->oid.hash, repo->packs); + target = find_oid_pack(&obj->oid, repo->packs); if (target) { obj->flags |= REMOTE; return 0; } obj->flags |= PUSHING; - request = xmalloc(sizeof(*request)); + CALLOC_ARRAY(request, 1); request->obj = obj; - request->url = NULL; request->lock = lock; - request->headers = NULL; request->state = NEED_PUSH; + strbuf_init(&request->buffer.buf, 0); request->next = request_queue_head; request_queue_head = request; @@ -912,6 +914,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout) result = XML_Parse(parser, in_buffer.buf, in_buffer.len, 1); free(ctx.name); + free(ctx.cdata); if (result != XML_STATUS_OK) { fprintf(stderr, "XML error: %s\n", XML_ErrorString( @@ -1169,6 +1172,7 @@ static void remote_ls(const char *path, int flags, result = XML_Parse(parser, in_buffer.buf, in_buffer.len, 1); free(ctx.name); + free(ctx.cdata); if (result != XML_STATUS_OK) { fprintf(stderr, "XML error: %s\n", @@ -1182,6 +1186,7 @@ static void remote_ls(const char *path, int flags, } free(ls.path); + free(ls.dentry_name); free(url); strbuf_release(&out_buffer.buf); strbuf_release(&in_buffer); @@ -1370,9 +1375,13 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock) } while (objects) { + struct object_list *next = objects->next; + if (!(objects->item->flags & UNINTERESTING)) count += add_send_request(objects->item, lock); - objects = objects->next; + + free(objects); + objects = next; } return count; @@ -1398,6 +1407,7 @@ static int update_remote(const struct object_id *oid, struct remote_lock *lock) if (start_active_slot(slot)) { run_active_slot(slot); strbuf_release(&out_buffer.buf); + curl_slist_free_all(dav_headers); if (results.curl_result != CURLE_OK) { fprintf(stderr, "PUT error: curl result=%d, HTTP code=%ld\n", @@ -1407,6 +1417,7 @@ static int update_remote(const struct object_id *oid, struct remote_lock *lock) } } else { strbuf_release(&out_buffer.buf); + curl_slist_free_all(dav_headers); fprintf(stderr, "Unable to start PUT request\n"); return 0; } @@ -1516,6 +1527,7 @@ static void update_remote_info_refs(struct remote_lock *lock) results.curl_result, results.http_code); } } + curl_slist_free_all(dav_headers); } strbuf_release(&buffer.buf); } @@ -1707,7 +1719,7 @@ int cmd_main(int argc, const char **argv) int rc = 0; int i; int new_refs; - struct ref *ref, *local_refs; + struct ref *ref, *local_refs = NULL; CALLOC_ARRAY(repo, 1); @@ -1972,6 +1984,7 @@ int cmd_main(int argc, const char **argv) cleanup: if (info_ref_lock) unlock_remote(info_ref_lock); + free(repo->url); free(repo); http_cleanup(); @@ -1983,5 +1996,8 @@ int cmd_main(int argc, const char **argv) request = next_request; } + refspec_clear(&rs); + free_refs(local_refs); + return rc; } diff --git a/http-walker.c b/http-walker.c index e417a7f51c..43cde0ebe5 100644 --- a/http-walker.c +++ b/http-walker.c @@ -74,7 +74,7 @@ static void start_object_request(struct object_request *obj_req) obj_req->state = ACTIVE; if (!start_active_slot(slot)) { obj_req->state = ABORTED; - release_http_object_request(req); + release_http_object_request(&req); return; } } @@ -110,7 +110,7 @@ static void process_object_response(void *callback_data) if (obj_req->repo->next) { obj_req->repo = obj_req->repo->next; - release_http_object_request(obj_req->req); + release_http_object_request(&obj_req->req); start_object_request(obj_req); return; } @@ -147,14 +147,14 @@ static int fill_active_slot(void *data UNUSED) return 0; } -static void prefetch(struct walker *walker, unsigned char *sha1) +static void prefetch(struct walker *walker, const struct object_id *oid) { struct object_request *newreq; struct walker_data *data = walker->data; newreq = xmalloc(sizeof(*newreq)); newreq->walker = walker; - oidread(&newreq->oid, sha1, the_repository->hash_algo); + oidcpy(&newreq->oid, oid); newreq->repo = data->alt; newreq->state = WAITING; newreq->req = NULL; @@ -422,7 +422,8 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo) return ret; } -static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1) +static int http_fetch_pack(struct walker *walker, struct alt_base *repo, + const struct object_id *oid) { struct packed_git *target; int ret; @@ -431,7 +432,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne if (fetch_indices(walker, repo)) return -1; - target = find_sha1_pack(sha1, repo->packs); + target = find_oid_pack(oid, repo->packs); if (!target) return -1; close_pack_index(target); @@ -440,7 +441,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne fprintf(stderr, "Getting pack %s\n", hash_to_hex(target->hash)); fprintf(stderr, " which contains %s\n", - hash_to_hex(sha1)); + oid_to_hex(oid)); } preq = new_http_pack_request(target->hash, repo->base); @@ -477,9 +478,9 @@ static void abort_object_request(struct object_request *obj_req) release_object_request(obj_req); } -static int fetch_object(struct walker *walker, unsigned char *hash) +static int fetch_object(struct walker *walker, const struct object_id *oid) { - char *hex = hash_to_hex(hash); + char *hex = oid_to_hex(oid); int ret = 0; struct object_request *obj_req = NULL; struct http_object_request *req; @@ -487,7 +488,7 @@ static int fetch_object(struct walker *walker, unsigned char *hash) list_for_each(pos, head) { obj_req = list_entry(pos, struct object_request, node); - if (hasheq(obj_req->oid.hash, hash, the_repository->hash_algo)) + if (oideq(&obj_req->oid, oid)) break; } if (!obj_req) @@ -495,7 +496,7 @@ static int fetch_object(struct walker *walker, unsigned char *hash) if (repo_has_object_file(the_repository, &obj_req->oid)) { if (obj_req->req) - abort_http_object_request(obj_req->req); + abort_http_object_request(&obj_req->req); abort_object_request(obj_req); return 0; } @@ -543,25 +544,25 @@ static int fetch_object(struct walker *walker, unsigned char *hash) strbuf_release(&buf); } - release_http_object_request(req); + release_http_object_request(&obj_req->req); release_object_request(obj_req); return ret; } -static int fetch(struct walker *walker, unsigned char *hash) +static int fetch(struct walker *walker, const struct object_id *oid) { struct walker_data *data = walker->data; struct alt_base *altbase = data->alt; - if (!fetch_object(walker, hash)) + if (!fetch_object(walker, oid)) return 0; while (altbase) { - if (!http_fetch_pack(walker, altbase, hash)) + if (!http_fetch_pack(walker, altbase, oid)) return 0; fetch_alternates(walker, data->alt->base); altbase = altbase->next; } - return error("Unable to find %s under %s", hash_to_hex(hash), + return error("Unable to find %s under %s", oid_to_hex(oid), data->alt->base); } @@ -579,8 +580,18 @@ static void cleanup(struct walker *walker) if (data) { alt = data->alt; while (alt) { + struct packed_git *pack; + alt_next = alt->next; + pack = alt->packs; + while (pack) { + struct packed_git *pack_next = pack->next; + close_pack(pack); + free(pack); + pack = pack_next; + } + free(alt->base); free(alt); @@ -19,6 +19,7 @@ #include "string-list.h" #include "object-file.h" #include "object-store-ll.h" +#include "tempfile.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); static int trace_curl_data = 1; @@ -52,22 +53,16 @@ static struct { { "sslv2", CURL_SSLVERSION_SSLv2 }, { "sslv3", CURL_SSLVERSION_SSLv3 }, { "tlsv1", CURL_SSLVERSION_TLSv1 }, -#ifdef GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0 { "tlsv1.0", CURL_SSLVERSION_TLSv1_0 }, { "tlsv1.1", CURL_SSLVERSION_TLSv1_1 }, { "tlsv1.2", CURL_SSLVERSION_TLSv1_2 }, -#endif -#ifdef GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_3 { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 }, -#endif }; static char *ssl_key; static char *ssl_key_type; static char *ssl_capath; static char *curl_no_proxy; -#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY static char *ssl_pinnedkey; -#endif static char *ssl_cainfo; static long curl_low_speed_limit = -1; static long curl_low_speed_time = -1; @@ -511,12 +506,7 @@ static int http_options(const char *var, const char *value, } if (!strcmp("http.pinnedpubkey", var)) { -#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY return git_config_pathname(&ssl_pinnedkey, var, value); -#else - warning(_("Public key pinning not supported with cURL < 7.39.0")); - return 0; -#endif } if (!strcmp("http.extraheader", var)) { @@ -700,7 +690,6 @@ static int has_cert_password(void) return 1; } -#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD static int has_proxy_cert_password(void) { if (http_proxy_ssl_cert == NULL || proxy_ssl_cert_password_required != 1) @@ -714,37 +703,12 @@ static int has_proxy_cert_password(void) } return 1; } -#endif -#ifdef GITCURL_HAVE_CURLOPT_TCP_KEEPALIVE static void set_curl_keepalive(CURL *c) { curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1); } -#else -static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type) -{ - int ka = 1; - int rc; - socklen_t len = (socklen_t)sizeof(ka); - - if (type != CURLSOCKTYPE_IPCXN) - return 0; - - rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len); - if (rc < 0) - warning_errno("unable to set SO_KEEPALIVE on socket"); - - return CURL_SOCKOPT_OK; -} - -static void set_curl_keepalive(CURL *c) -{ - curl_easy_setopt(c, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); -} -#endif - /* Return 1 if redactions have been made, 0 otherwise. */ static int redact_sensitive_header(struct strbuf *header, size_t offset) { @@ -800,6 +764,7 @@ static int redact_sensitive_header(struct strbuf *header, size_t offset) strbuf_setlen(header, sensitive_header - header->buf); strbuf_addbuf(header, &redacted_header); + strbuf_release(&redacted_header); ret = 1; } return ret; @@ -1012,7 +977,6 @@ static long get_curl_allowed_protocols(int from_user, struct strbuf *list) return bits; } -#ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2 static int get_curl_http_version_opt(const char *version_string, long *opt) { int i; @@ -1035,8 +999,6 @@ static int get_curl_http_version_opt(const char *version_string, long *opt) return -1; /* not found */ } -#endif - static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); @@ -1054,7 +1016,6 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2); } -#ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2 if (curl_http_version) { long opt; if (!get_curl_http_version_opt(curl_http_version, &opt)) { @@ -1062,7 +1023,6 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_HTTP_VERSION, opt); } } -#endif curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY); @@ -1085,11 +1045,7 @@ static CURL *get_curl_handle(void) if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) && !http_schannel_check_revoke) { -#ifdef GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); -#else - warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0")); -#endif } if (http_proactive_auth != PROACTIVE_AUTH_NONE) @@ -1129,23 +1085,17 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_SSLKEYTYPE, ssl_key_type); if (ssl_capath) curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath); -#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY if (ssl_pinnedkey) curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey); -#endif if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) && !http_schannel_use_ssl_cainfo) { curl_easy_setopt(result, CURLOPT_CAINFO, NULL); -#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL); -#endif } else if (ssl_cainfo != NULL || http_proxy_ssl_ca_info != NULL) { if (ssl_cainfo) curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo); -#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO if (http_proxy_ssl_ca_info) curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, http_proxy_ssl_ca_info); -#endif } if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) { @@ -1227,6 +1177,8 @@ static CURL *get_curl_handle(void) */ curl_easy_setopt(result, CURLOPT_PROXY, ""); } else if (curl_http_proxy) { + struct strbuf proxy = STRBUF_INIT; + if (starts_with(curl_http_proxy, "socks5h")) curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); @@ -1239,7 +1191,6 @@ static CURL *get_curl_handle(void) else if (starts_with(curl_http_proxy, "socks")) curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); -#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD else if (starts_with(curl_http_proxy, "https")) { curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); @@ -1252,7 +1203,6 @@ static CURL *get_curl_handle(void) if (has_proxy_cert_password()) curl_easy_setopt(result, CURLOPT_PROXY_KEYPASSWD, proxy_cert_auth.password); } -#endif if (strstr(curl_http_proxy, "://")) credential_from_url(&proxy_auth, curl_http_proxy); else { @@ -1265,7 +1215,27 @@ static CURL *get_curl_handle(void) if (!proxy_auth.host) die("Invalid proxy URL '%s'", curl_http_proxy); - curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host); + strbuf_addstr(&proxy, proxy_auth.host); + if (proxy_auth.path) { + curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW); + + if (ver->version_num < 0x075400) + die("libcurl 7.84 or later is required to support paths in proxy URLs"); + + if (!starts_with(proxy_auth.protocol, "socks")) + die("Invalid proxy URL '%s': only SOCKS proxies support paths", + curl_http_proxy); + + if (strcasecmp(proxy_auth.host, "localhost")) + die("Invalid proxy URL '%s': host must be localhost if a path is present", + curl_http_proxy); + + strbuf_addch(&proxy, '/'); + strbuf_add_percentencode(&proxy, proxy_auth.path, 0); + } + curl_easy_setopt(result, CURLOPT_PROXY, proxy.buf); + strbuf_release(&proxy); + var_override(&curl_no_proxy, getenv("NO_PROXY")); var_override(&curl_no_proxy, getenv("no_proxy")); curl_easy_setopt(result, CURLOPT_NOPROXY, curl_no_proxy); @@ -1306,7 +1276,6 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) free(normalized_url); string_list_clear(&config.vars, 1); -#ifdef GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS if (http_ssl_backend) { const curl_ssl_backend **backends; struct strbuf buf = STRBUF_INIT; @@ -1331,7 +1300,6 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) break; /* Okay! */ } } -#endif if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) die("curl_global_init failed"); @@ -1685,7 +1653,7 @@ void run_active_slot(struct active_request_slot *slot) * The value of slot->finished we set before the loop was used * to set our "finished" variable when our request completed. * - * 1. The slot may not have been reused for another requst + * 1. The slot may not have been reused for another request * yet, in which case it still has &finished. * * 2. The slot may already be in-use to serve another request, @@ -1828,10 +1796,8 @@ static int handle_curl_result(struct slot_results *results) */ credential_reject(&cert_auth); return HTTP_NOAUTH; -#ifdef GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH } else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) { return HTTP_NOMATCHPUBLICKEY; -#endif } else if (missing_target(results)) return HTTP_MISSING_TARGET; else if (results->http_code == 401) { @@ -2267,17 +2233,19 @@ static int http_request_reauth(const char *url, case HTTP_REQUEST_STRBUF: strbuf_reset(result); break; - case HTTP_REQUEST_FILE: - if (fflush(result)) { + case HTTP_REQUEST_FILE: { + FILE *f = result; + if (fflush(f)) { error_errno("unable to flush a file"); return HTTP_START_FAILED; } - rewind(result); - if (ftruncate(fileno(result), 0) < 0) { + rewind(f); + if (ftruncate(fileno(f), 0) < 0) { error_errno("unable to truncate a file"); return HTTP_START_FAILED; } break; + } default: BUG("Unknown http_request target"); } @@ -2365,8 +2333,24 @@ static char *fetch_pack_index(unsigned char *hash, const char *base_url) strbuf_addf(&buf, "objects/pack/pack-%s.idx", hash_to_hex(hash)); url = strbuf_detach(&buf, NULL); - strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(hash)); - tmp = strbuf_detach(&buf, NULL); + /* + * Don't put this into packs/, since it's just temporary and we don't + * want to confuse it with our local .idx files. We'll generate our + * own index if we choose to download the matching packfile. + * + * It's tempting to use xmks_tempfile() here, but it's important that + * the file not exist, otherwise http_get_file() complains. So we + * create a filename that should be unique, and then just register it + * as a tempfile so that it will get cleaned up on exit. + * + * In theory we could hold on to the tempfile and delete these as soon + * as we download the matching pack, but it would take a bit of + * refactoring. Leaving them until the process ends is probably OK. + */ + tmp = xstrfmt("%s/tmp_pack_%s.idx", + repo_get_object_directory(the_repository), + hash_to_hex(hash)); + register_tempfile(tmp); if (http_get_file(url, tmp, NULL) != HTTP_OK) { error("Unable to get pack index %s", url); @@ -2380,22 +2364,24 @@ static char *fetch_pack_index(unsigned char *hash, const char *base_url) static int fetch_and_setup_pack_index(struct packed_git **packs_head, unsigned char *sha1, const char *base_url) { - struct packed_git *new_pack; + struct packed_git *new_pack, *p; char *tmp_idx = NULL; int ret; - if (has_pack_index(sha1)) { - new_pack = parse_pack_index(sha1, sha1_pack_index_name(sha1)); - if (!new_pack) - return -1; /* parse_pack_index() already issued error message */ - goto add_pack; + /* + * If we already have the pack locally, no need to fetch its index or + * even add it to list; we already have all of its objects. + */ + for (p = get_all_packs(the_repository); p; p = p->next) { + if (hasheq(p->hash, sha1, the_repository->hash_algo)) + return 0; } tmp_idx = fetch_pack_index(sha1, base_url); if (!tmp_idx) return -1; - new_pack = parse_pack_index(sha1, tmp_idx); + new_pack = parse_pack_index(the_repository, sha1, tmp_idx); if (!new_pack) { unlink(tmp_idx); free(tmp_idx); @@ -2404,15 +2390,12 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head, } ret = verify_pack_index(new_pack); - if (!ret) { + if (!ret) close_pack_index(new_pack); - ret = finalize_object_file(tmp_idx, sha1_pack_index_name(sha1)); - } free(tmp_idx); if (ret) return -1; -add_pack: new_pack->next = *packs_head; *packs_head = new_pack; return 0; @@ -2452,6 +2435,7 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head) cleanup: free(url); + strbuf_release(&buf); return ret; } @@ -2539,7 +2523,8 @@ struct http_pack_request *new_direct_http_pack_request( preq->url = url; - strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(packed_git_hash)); + odb_pack_name(the_repository, &preq->tmpfile, packed_git_hash, "pack"); + strbuf_addstr(&preq->tmpfile, ".temp"); preq->packfile = fopen(preq->tmpfile.buf, "a"); if (!preq->packfile) { error("Unable to open local file %s for pack", @@ -2703,6 +2688,7 @@ struct http_object_request *new_http_object_request(const char *base_url, * file; also rewind to the beginning of the local file. */ if (prev_read == -1) { + git_inflate_end(&freq->stream); memset(&freq->stream, 0, sizeof(freq->stream)); git_inflate_init(&freq->stream); the_hash_algo->init_fn(&freq->c); @@ -2776,7 +2762,6 @@ int finish_http_object_request(struct http_object_request *freq) return -1; } - git_inflate_end(&freq->stream); the_hash_algo->final_oid_fn(&freq->real_oid, &freq->c); if (freq->zret != Z_STREAM_END) { unlink_or_warn(freq->tmpfile.buf); @@ -2793,15 +2778,17 @@ int finish_http_object_request(struct http_object_request *freq) return freq->rename; } -void abort_http_object_request(struct http_object_request *freq) +void abort_http_object_request(struct http_object_request **freq_p) { + struct http_object_request *freq = *freq_p; unlink_or_warn(freq->tmpfile.buf); - release_http_object_request(freq); + release_http_object_request(freq_p); } -void release_http_object_request(struct http_object_request *freq) +void release_http_object_request(struct http_object_request **freq_p) { + struct http_object_request *freq = *freq_p; if (freq->localfile != -1) { close(freq->localfile); freq->localfile = -1; @@ -2815,4 +2802,8 @@ void release_http_object_request(struct http_object_request *freq) } curl_slist_free_all(freq->headers); strbuf_release(&freq->tmpfile); + git_inflate_end(&freq->stream); + + free(freq); + *freq_p = NULL; } @@ -240,8 +240,8 @@ struct http_object_request *new_http_object_request( const char *base_url, const struct object_id *oid); void process_http_object_request(struct http_object_request *freq); int finish_http_object_request(struct http_object_request *freq); -void abort_http_object_request(struct http_object_request *freq); -void release_http_object_request(struct http_object_request *freq); +void abort_http_object_request(struct http_object_request **freq); +void release_http_object_request(struct http_object_request **freq); /* * Instead of using environment variables to determine if curl tracing happens, diff --git a/imap-send.c b/imap-send.c index 01404e5047..25c68fd90d 100644 --- a/imap-send.c +++ b/imap-send.c @@ -21,6 +21,8 @@ * along with this program; if not, see <https://www.gnu.org/licenses/>. */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "credential.h" @@ -29,9 +31,6 @@ #include "parse-options.h" #include "setup.h" #include "strbuf.h" -#if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG) -typedef void *SSL; -#endif #ifdef USE_CURL_FOR_IMAP_SEND #include "http.h" #endif @@ -83,7 +82,11 @@ struct imap_server_conf { struct imap_socket { int fd[2]; +#if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG) + void *ssl; +#else SSL *ssl; +#endif }; struct imap_buffer { @@ -190,7 +193,7 @@ static void socket_perror(const char *func, struct imap_socket *sock, int ret) #ifdef NO_OPENSSL static int ssl_socket_connect(struct imap_socket *sock UNUSED, - const struct imap_server_conf *cfg, + const struct imap_server_conf *cfg UNUSED, int use_tls_only UNUSED) { fprintf(stderr, "SSL requested but SSL support not compiled in\n"); @@ -665,12 +668,12 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb, return RESP_BAD; } if (!strcmp("UIDVALIDITY", arg)) { - if (!(arg = next_arg(&s)) || !(ctx->uidvalidity = atoi(arg))) { + if (!(arg = next_arg(&s)) || strtol_i(arg, 10, &ctx->uidvalidity) || !ctx->uidvalidity) { fprintf(stderr, "IMAP error: malformed UIDVALIDITY status\n"); return RESP_BAD; } } else if (!strcmp("UIDNEXT", arg)) { - if (!(arg = next_arg(&s)) || !(imap->uidnext = atoi(arg))) { + if (!(arg = next_arg(&s)) || strtol_i(arg, 10, &imap->uidnext) || !imap->uidnext) { fprintf(stderr, "IMAP error: malformed NEXTUID status\n"); return RESP_BAD; } @@ -683,8 +686,8 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb, for (; isspace((unsigned char)*p); p++); fprintf(stderr, "*** IMAP ALERT *** %s\n", p); } else if (cb && cb->ctx && !strcmp("APPENDUID", arg)) { - if (!(arg = next_arg(&s)) || !(ctx->uidvalidity = atoi(arg)) || - !(arg = next_arg(&s)) || !(*(int *)cb->ctx = atoi(arg))) { + if (!(arg = next_arg(&s)) || strtol_i(arg, 10, &ctx->uidvalidity) || !ctx->uidvalidity || + !(arg = next_arg(&s)) || strtol_i(arg, 10, (int *)cb->ctx) || !cb->ctx) { fprintf(stderr, "IMAP error: malformed APPENDUID status\n"); return RESP_BAD; } @@ -770,7 +773,10 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd) if (!tcmd) return DRV_OK; } else { - tag = atoi(arg); + if (strtol_i(arg, 10, &tag)) { + fprintf(stderr, "IMAP error: malformed tag %s\n", arg); + return RESP_BAD; + } for (pcmdp = &imap->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next) if (cmdp->tag == tag) goto gottag; @@ -1414,15 +1420,11 @@ static CURL *setup_curl(struct imap_server_conf *srvc, struct credential *cred) curl_easy_setopt(curl, CURLOPT_PORT, srvc->port); if (srvc->auth_method) { -#ifndef GIT_CURL_HAVE_CURLOPT_LOGIN_OPTIONS - warning("No LOGIN_OPTIONS support in this cURL version"); -#else struct strbuf auth = STRBUF_INIT; strbuf_addstr(&auth, "AUTH="); strbuf_addstr(&auth, srvc->auth_method); curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, auth.buf); strbuf_release(&auth); -#endif } if (!srvc->use_ssl) diff --git a/line-log.c b/line-log.c index 67c80b39a0..bc67b75d10 100644 --- a/line-log.c +++ b/line-log.c @@ -248,8 +248,10 @@ static void line_log_data_init(struct line_log_data *r) static void line_log_data_clear(struct line_log_data *r) { range_set_release(&r->ranges); + free(r->path); if (r->pair) diff_free_filepair(r->pair); + diff_ranges_release(&r->diff); } static void free_line_log_data(struct line_log_data *r) @@ -571,7 +573,8 @@ parse_lines(struct repository *r, struct commit *commit, struct line_log_data *p; for_each_string_list_item(item, args) { - const char *name_part, *range_part; + const char *name_part; + char *range_part; char *full_name; struct diff_filespec *spec; long begin = 0, end = 0; @@ -615,6 +618,7 @@ parse_lines(struct repository *r, struct commit *commit, free_filespec(spec); FREE_AND_NULL(ends); + free(range_part); } for (p = ranges; p; p = p->next) @@ -760,15 +764,13 @@ static void parse_pathspec_from_ranges(struct pathspec *pathspec, { struct line_log_data *r; struct strvec array = STRVEC_INIT; - const char **paths; for (r = range; r; r = r->next) strvec_push(&array, r->path); - paths = strvec_detach(&array); - parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", paths); - /* strings are now owned by pathspec */ - free(paths); + parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", array.v); + + strvec_clear(&array); } void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args) @@ -781,21 +783,22 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list add_line_range(rev, commit, range); parse_pathspec_from_ranges(&rev->diffopt.pathspec, range); + + free_line_log_data(range); } static void move_diff_queue(struct diff_queue_struct *dst, struct diff_queue_struct *src) { assert(src != dst); - memcpy(dst, src, sizeof(struct diff_queue_struct)); - DIFF_QUEUE_CLEAR(src); + memcpy(dst, src, sizeof(*dst)); + diff_queue_init(src); } static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions) { int i; - struct diff_queue_struct outq; - DIFF_QUEUE_CLEAR(&outq); + struct diff_queue_struct outq = DIFF_QUEUE_INIT; for (i = 0; i < diff_queued_diff.nr; i++) { struct diff_filepair *p = diff_queued_diff.queue[i]; @@ -850,12 +853,12 @@ static void queue_diffs(struct line_log_data *range, clear_pathspec(&opt->pathspec); parse_pathspec_from_ranges(&opt->pathspec, range); } - DIFF_QUEUE_CLEAR(&diff_queued_diff); + diff_queue_clear(&diff_queued_diff); diff_tree_oid(parent_tree_oid, tree_oid, "", opt); if (opt->detect_rename && diff_might_be_rename()) { /* must look at the full tree diff to detect renames */ clear_pathspec(&opt->pathspec); - DIFF_QUEUE_CLEAR(&diff_queued_diff); + diff_queue_clear(&diff_queued_diff); diff_tree_oid(parent_tree_oid, tree_oid, "", opt); @@ -897,16 +900,6 @@ static void print_line(const char *prefix, char first, fputs("\\ No newline at end of file\n", file); } -static char *output_prefix(struct diff_options *opt) -{ - if (opt->output_prefix) { - struct strbuf *sb = opt->output_prefix(opt, opt->output_prefix_data); - return sb->buf; - } else { - return xstrdup(""); - } -} - static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *range) { unsigned int i, j = 0; @@ -916,7 +909,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang struct diff_ranges *diff = &range->diff; struct diff_options *opt = &rev->diffopt; - char *prefix = output_prefix(opt); + const char *prefix = diff_line_prefix(opt); const char *c_reset = diff_get_color(opt->use_color, DIFF_RESET); const char *c_frag = diff_get_color(opt->use_color, DIFF_FRAGINFO); const char *c_meta = diff_get_color(opt->use_color, DIFF_METAINFO); @@ -1003,7 +996,6 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang out: free(p_ends); free(t_ends); - free(prefix); } /* @@ -1012,10 +1004,9 @@ out: */ static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range) { - char *prefix = output_prefix(&rev->diffopt); + const char *prefix = diff_line_prefix(&rev->diffopt); fprintf(rev->diffopt.file, "%s\n", prefix); - free(prefix); while (range) { dump_diff_hacky_one(rev, range); @@ -1097,7 +1088,7 @@ static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair) static void free_diffqueues(int n, struct diff_queue_struct *dq) { for (int i = 0; i < n; i++) - diff_free_queue(&dq[i]); + diff_queue_clear(&dq[i]); free(dq); } @@ -1132,10 +1123,18 @@ static int process_all_files(struct line_log_data **range_out, while (rg && strcmp(rg->path, pair->two->path)) rg = rg->next; assert(rg); + if (rg->pair) + diff_free_filepair(rg->pair); rg->pair = diff_filepair_dup(queue->queue[i]); + diff_ranges_release(&rg->diff); memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges)); + FREE_AND_NULL(pairdiff); + } + + if (pairdiff) { + diff_ranges_release(pairdiff); + free(pairdiff); } - free(pairdiff); } return changed; @@ -1200,7 +1199,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c if (parent) add_line_range(rev, parent, parent_range); free_line_log_data(parent_range); - diff_free_queue(&queue); + diff_queue_clear(&queue); return changed; } @@ -1213,12 +1212,13 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm struct commit_list *p; int i; int nparents = commit_list_count(commit->parents); + int ret; if (nparents > 1 && rev->first_parent_only) nparents = 1; ALLOC_ARRAY(diffqueues, nparents); - ALLOC_ARRAY(cand, nparents); + CALLOC_ARRAY(cand, nparents); ALLOC_ARRAY(parents, nparents); p = commit->parents; @@ -1230,7 +1230,6 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm for (i = 0; i < nparents; i++) { int changed; - cand[i] = NULL; changed = process_all_files(&cand[i], rev, &diffqueues[i], range); if (!changed) { /* @@ -1238,13 +1237,11 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm * don't follow any other path in history */ add_line_range(rev, parents[i], cand[i]); - clear_commit_line_range(rev, commit); + free_commit_list(commit->parents); commit_list_append(parents[i], &commit->parents); - free(parents); - free(cand); - free_diffqueues(nparents, diffqueues); - /* NEEDSWORK leaking like a sieve */ - return 0; + + ret = 0; + goto out; } } @@ -1252,18 +1249,25 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm * No single parent took the blame. We add the candidates * from the above loop to the parents. */ - for (i = 0; i < nparents; i++) { + for (i = 0; i < nparents; i++) add_line_range(rev, parents[i], cand[i]); - } + ret = 1; + +out: clear_commit_line_range(rev, commit); free(parents); + for (i = 0; i < nparents; i++) { + if (!cand[i]) + continue; + line_log_data_clear(cand[i]); + free(cand[i]); + } free(cand); free_diffqueues(nparents, diffqueues); - return 1; + return ret; /* NEEDSWORK evil merge detection stuff */ - /* NEEDSWORK leaking like a sieve */ } int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit) diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c index 00611107d2..fa72e81e4a 100644 --- a/list-objects-filter-options.c +++ b/list-objects-filter-options.c @@ -252,16 +252,14 @@ void parse_list_objects_filter( const char *arg) { struct strbuf errbuf = STRBUF_INIT; - int parse_error; if (!filter_options->filter_spec.buf) BUG("filter_options not properly initialized"); if (!filter_options->choice) { + if (gently_parse_list_objects_filter(filter_options, arg, &errbuf)) + die("%s", errbuf.buf); strbuf_addstr(&filter_options->filter_spec, arg); - - parse_error = gently_parse_list_objects_filter( - filter_options, arg, &errbuf); } else { struct list_objects_filter_options *sub; @@ -271,18 +269,17 @@ void parse_list_objects_filter( */ transform_to_combine_type(filter_options); - strbuf_addch(&filter_options->filter_spec, '+'); - filter_spec_append_urlencode(filter_options, arg); ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1, filter_options->sub_alloc); sub = &filter_options->sub[filter_options->sub_nr - 1]; list_objects_filter_init(sub); - parse_error = gently_parse_list_objects_filter(sub, arg, - &errbuf); + if (gently_parse_list_objects_filter(sub, arg, &errbuf)) + die("%s", errbuf.buf); + + strbuf_addch(&filter_options->filter_spec, '+'); + filter_spec_append_urlencode(filter_options, arg); } - if (parse_error) - die("%s", errbuf.buf); } int opt_parse_list_objects_filter(const struct option *opt, diff --git a/list-objects.c b/list-objects.c index 985d008799..d11a389b3a 100644 --- a/list-objects.c +++ b/list-objects.c @@ -41,7 +41,8 @@ static void show_object(struct traversal_context *ctx, { if (!ctx->show_object) return; - if (ctx->revs->unpacked && has_object_pack(&object->oid)) + if (ctx->revs->unpacked && has_object_pack(ctx->revs->repo, + &object->oid)) return; ctx->show_object(object, name, ctx->show_data); @@ -74,7 +75,7 @@ static void process_blob(struct traversal_context *ctx, */ if (ctx->revs->exclude_promisor_objects && !repo_has_object_file(the_repository, &obj->oid) && - is_promisor_object(&obj->oid)) + is_promisor_object(ctx->revs->repo, &obj->oid)) return; pathlen = path->len; @@ -179,7 +180,7 @@ static void process_tree(struct traversal_context *ctx, * an incomplete list of missing objects. */ if (revs->exclude_promisor_objects && - is_promisor_object(&obj->oid)) + is_promisor_object(revs->repo, &obj->oid)) return; if (!revs->do_not_die_on_missing_objects) diff --git a/log-tree.c b/log-tree.c index 52feec4356..83cc4b1cfb 100644 --- a/log-tree.c +++ b/log-tree.c @@ -31,6 +31,7 @@ #include "tree.h" #include "wildmatch.h" #include "write-or-die.h" +#include "pager.h" static struct decoration name_decoration = { "object names" }; static int decoration_loaded; @@ -145,7 +146,7 @@ static int ref_filter_match(const char *refname, return 1; } -static int add_ref_decoration(const char *refname, const struct object_id *oid, +static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -231,6 +232,11 @@ void load_ref_decorations(struct decoration_filter *filter, int flags) for_each_string_list_item(item, filter->exclude_ref_config_pattern) { normalize_glob_ref(item, NULL, item->string); } + + /* normalize_glob_ref duplicates the strings */ + filter->exclude_ref_pattern->strdup_strings = 1; + filter->include_ref_pattern->strdup_strings = 1; + filter->exclude_ref_config_pattern->strdup_strings = 1; } decoration_loaded = 1; decoration_flags = flags; @@ -242,6 +248,27 @@ void load_ref_decorations(struct decoration_filter *filter, int flags) } } +void load_branch_decorations(void) +{ + if (!decoration_loaded) { + struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP; + struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP; + struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP; + struct decoration_filter decoration_filter = { + .include_ref_pattern = &decorate_refs_include, + .exclude_ref_pattern = &decorate_refs_exclude, + .exclude_ref_config_pattern = &decorate_refs_exclude_config, + }; + + string_list_append(&decorate_refs_include, "refs/heads/"); + load_ref_decorations(&decoration_filter, 0); + + string_list_clear(&decorate_refs_exclude, 0); + string_list_clear(&decorate_refs_exclude_config, 0); + string_list_clear(&decorate_refs_include, 0); + } +} + static void show_parents(struct commit *commit, int abbrev, FILE *file) { struct commit_list *p; @@ -411,16 +438,6 @@ void show_decorations(struct rev_info *opt, struct commit *commit) strbuf_release(&sb); } -static unsigned int digits_in_number(unsigned int number) -{ - unsigned int i = 10, result = 1; - while (i <= number) { - i *= 10; - result++; - } - return result; -} - void fmt_output_subject(struct strbuf *filename, const char *subject, struct rev_info *info) @@ -464,7 +481,7 @@ void fmt_output_email_subject(struct strbuf *sb, struct rev_info *opt) strbuf_addf(sb, "Subject: [%s%s%0*d/%d] ", opt->subject_prefix, *opt->subject_prefix ? " " : "", - digits_in_number(opt->total), + decimal_width(opt->total), opt->nr, opt->total); } else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) { strbuf_addf(sb, "Subject: [%s] ", @@ -684,7 +701,7 @@ static void show_diff_of_diff(struct rev_info *opt) struct diff_queue_struct dq; memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); - DIFF_QUEUE_CLEAR(&diff_queued_diff); + diff_queue_init(&diff_queued_diff); fprintf_ln(opt->diffopt.file, "\n%s", opt->idiff_title); show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2, @@ -703,7 +720,7 @@ static void show_diff_of_diff(struct rev_info *opt) }; memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); - DIFF_QUEUE_CLEAR(&diff_queued_diff); + diff_queue_init(&diff_queued_diff); fprintf_ln(opt->diffopt.file, "\n%s", opt->rdiff_title); /* @@ -931,12 +948,7 @@ int log_tree_diff_flush(struct rev_info *opt) * diff/diffstat output for readability. */ int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH; - if (opt->diffopt.output_prefix) { - struct strbuf *msg = NULL; - msg = opt->diffopt.output_prefix(&opt->diffopt, - opt->diffopt.output_prefix_data); - fwrite(msg->buf, msg->len, 1, opt->diffopt.file); - } + fputs(diff_line_prefix(&opt->diffopt), opt->diffopt.file); /* * We may have shown three-dashes line early @@ -1024,8 +1036,19 @@ static int do_remerge_diff(struct rev_info *opt, struct strbuf parent1_desc = STRBUF_INIT; struct strbuf parent2_desc = STRBUF_INIT; + /* + * Lazily prepare a temporary object directory and rotate it + * into the alternative object store list as the primary. + */ + if (opt->remerge_diff && !opt->remerge_objdir) { + opt->remerge_objdir = tmp_objdir_create("remerge-diff"); + if (!opt->remerge_objdir) + return error(_("unable to create temporary object directory")); + tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1); + } + /* Setup merge options */ - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.show_rename_progress = 0; o.record_conflict_msgs_as_headers = 1; o.msg_header_prefix = "remerge"; @@ -1060,10 +1083,7 @@ static int do_remerge_diff(struct rev_info *opt, merge_finalize(&o, &res); /* Clean up the contents of the temporary object directory */ - if (opt->remerge_objdir) - tmp_objdir_discard_objects(opt->remerge_objdir); - else - BUG("did a remerge diff without remerge_objdir?!?"); + tmp_objdir_discard_objects(opt->remerge_objdir); return !opt->loginfo; } diff --git a/log-tree.h b/log-tree.h index 94978e2c83..ebe491c543 100644 --- a/log-tree.h +++ b/log-tree.h @@ -33,6 +33,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, int *need_8bit_cte_p, int maybe_multipart); void load_ref_decorations(struct decoration_filter *filter, int flags); +void load_branch_decorations(void); void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *); void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *); @@ -1,10 +1,9 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "hash.h" #include "path.h" #include "object-store.h" #include "hex.h" +#include "repository.h" #include "wrapper.h" #include "gettext.h" #include "loose.h" @@ -142,8 +141,8 @@ int repo_write_loose_object_map(struct repository *repo) for (; iter != kh_end(map); iter++) { if (kh_exist(map, iter)) { - if (oideq(&kh_key(map, iter), the_hash_algo->empty_tree) || - oideq(&kh_key(map, iter), the_hash_algo->empty_blob)) + if (oideq(&kh_key(map, iter), repo->hash_algo->empty_tree) || + oideq(&kh_key(map, iter), repo->hash_algo->empty_blob)) continue; strbuf_addf(&buf, "%s %s\n", oid_to_hex(&kh_key(map, iter)), oid_to_hex(kh_value(map, iter))); if (write_in_full(fd, buf.buf, buf.len) < 0) @@ -162,7 +161,7 @@ int repo_write_loose_object_map(struct repository *repo) errout: rollback_lock_file(&lock); strbuf_release(&buf); - error_errno(_("failed to write loose object index %s\n"), path.buf); + error_errno(_("failed to write loose object index %s"), path.buf); strbuf_release(&path); return -1; } @@ -197,7 +196,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid strbuf_release(&path); return 0; errout: - error_errno(_("failed to write loose object index %s\n"), path.buf); + error_errno(_("failed to write loose object index %s"), path.buf); close(fd); rollback_lock_file(&lock); strbuf_release(&buf); @@ -77,7 +77,7 @@ struct ls_refs_data { unsigned unborn : 1; }; -static int send_ref(const char *refname, const struct object_id *oid, +static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { struct ls_refs_data *data = cb_data; @@ -135,7 +135,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data) oid_is_null = is_null_oid(&oid); if (!oid_is_null || (data->unborn && data->symrefs && (flag & REF_ISSYMREF))) - send_ref(namespaced.buf, oid_is_null ? NULL : &oid, flag, data); + send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data); strbuf_release(&namespaced); } diff --git a/mailinfo.c b/mailinfo.c index 94b9b0abf2..d1f42bd7e3 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "gettext.h" @@ -346,9 +348,8 @@ static void cleanup_subject(struct mailinfo *mi, struct strbuf *subject) strbuf_trim(subject); } -#define MAX_HDR_PARSED 10 -static const char *header[MAX_HDR_PARSED] = { - "From","Subject","Date", +static const char * const header[] = { + "From", "Subject", "Date", }; static inline int skip_header(const struct strbuf *line, const char *hdr, @@ -583,7 +584,7 @@ static int check_header(struct mailinfo *mi, struct strbuf sb = STRBUF_INIT; /* search for the interesting parts */ - for (i = 0; header[i]; i++) { + for (i = 0; i < ARRAY_SIZE(header); i++) { if ((!hdr_data[i] || overwrite) && parse_header(line, header[i], mi, &sb)) { handle_header(&hdr_data[i], &sb); @@ -625,7 +626,7 @@ static int is_inbody_header(const struct mailinfo *mi, { int i; const char *val; - for (i = 0; header[i]; i++) + for (i = 0; i < ARRAY_SIZE(header); i++) if (!mi->s_hdr_data[i] && skip_header(line, header[i], &val)) return 1; return 0; @@ -772,7 +773,7 @@ static int check_inbody_header(struct mailinfo *mi, const struct strbuf *line) return is_format_patch_separator(line->buf + 1, line->len - 1); if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { int i; - for (i = 0; header[i]; i++) + for (i = 0; i < ARRAY_SIZE(header); i++) if (!strcmp("Subject", header[i])) { handle_header(&mi->s_hdr_data[i], line); return 1; @@ -824,7 +825,7 @@ static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line) * We may have already read "secondary headers"; purge * them to give ourselves a clean restart. */ - for (i = 0; header[i]; i++) { + for (i = 0; i < ARRAY_SIZE(header); i++) { if (mi->s_hdr_data[i]) strbuf_release(mi->s_hdr_data[i]); FREE_AND_NULL(mi->s_hdr_data[i]); @@ -1155,7 +1156,7 @@ static void handle_info(struct mailinfo *mi) struct strbuf *hdr; int i; - for (i = 0; header[i]; i++) { + for (i = 0; i < ARRAY_SIZE(header); i++) { /* only print inbody headers if we output a patch file */ if (mi->patch_lines && mi->s_hdr_data[i]) hdr = mi->s_hdr_data[i]; @@ -1206,8 +1207,8 @@ int mailinfo(struct mailinfo *mi, const char *msg, const char *patch) return -1; } - mi->p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*(mi->p_hdr_data))); - mi->s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*(mi->s_hdr_data))); + mi->p_hdr_data = xcalloc(ARRAY_SIZE(header), sizeof(*(mi->p_hdr_data))); + mi->s_hdr_data = xcalloc(ARRAY_SIZE(header), sizeof(*(mi->s_hdr_data))); do { peek = fgetc(mi->input); @@ -1290,8 +1291,21 @@ void clear_mailinfo(struct mailinfo *mi) strbuf_release(&mi->inbody_header_accum); free(mi->message_id); - strbuf_list_free(mi->p_hdr_data); - strbuf_list_free(mi->s_hdr_data); + for (size_t i = 0; i < ARRAY_SIZE(header); i++) { + if (!mi->p_hdr_data[i]) + continue; + strbuf_release(mi->p_hdr_data[i]); + free(mi->p_hdr_data[i]); + } + free(mi->p_hdr_data); + + for (size_t i = 0; i < ARRAY_SIZE(header); i++) { + if (!mi->s_hdr_data[i]) + continue; + strbuf_release(mi->s_hdr_data[i]); + free(mi->s_hdr_data[i]); + } + free(mi->s_hdr_data); while (mi->content < mi->content_top) { free(*(mi->content_top)); @@ -142,11 +142,8 @@ static void read_mailmap_line(struct string_list *map, char *buffer) add_mapping(map, name1, email1, name2, email2); } -/* Flags for read_mailmap_file() */ -#define MAILMAP_NOFOLLOW (1<<0) - -static int read_mailmap_file(struct string_list *map, const char *filename, - unsigned flags) +int read_mailmap_file(struct string_list *map, const char *filename, + unsigned flags) { char buffer[1024]; FILE *f; @@ -186,7 +183,7 @@ static void read_mailmap_string(struct string_list *map, char *buf) } } -static int read_mailmap_blob(struct string_list *map, const char *name) +int read_mailmap_blob(struct string_list *map, const char *name) { struct object_id oid; char *buf; @@ -201,8 +198,10 @@ static int read_mailmap_blob(struct string_list *map, const char *name) buf = repo_read_object_file(the_repository, &oid, &type, &size); if (!buf) return error("unable to read mailmap object at %s", name); - if (type != OBJ_BLOB) + if (type != OBJ_BLOB) { + free(buf); return error("mailmap is not a blob: %s", name); + } read_mailmap_string(map, buf); @@ -6,6 +6,13 @@ struct string_list; extern char *git_mailmap_file; extern char *git_mailmap_blob; +/* Flags for read_mailmap_file() */ +#define MAILMAP_NOFOLLOW (1<<0) + +int read_mailmap_file(struct string_list *map, const char *filename, + unsigned flags); +int read_mailmap_blob(struct string_list *map, const char *name); + int read_mailmap(struct string_list *map); void clear_mailmap(struct string_list *map); diff --git a/match-trees.c b/match-trees.c index f17c74d483..147b03abf1 100644 --- a/match-trees.c +++ b/match-trees.c @@ -294,18 +294,22 @@ void shift_tree(struct repository *r, unsigned short mode; if (!*del_prefix) - return; + goto out; if (get_tree_entry(r, hash2, del_prefix, shifted, &mode)) die("cannot find path %s in tree %s", del_prefix, oid_to_hex(hash2)); - return; + goto out; } if (!*add_prefix) - return; + goto out; splice_tree(hash1, add_prefix, hash2, shifted); + +out: + free(add_prefix); + free(del_prefix); } /* diff --git a/merge-ll.c b/merge-ll.c index 180c19df67..62fc625552 100644 --- a/merge-ll.c +++ b/merge-ll.c @@ -4,6 +4,8 @@ * Copyright (c) 2007 Junio C Hamano */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "convert.h" @@ -13,6 +15,7 @@ #include "merge-ll.h" #include "quote.h" #include "strbuf.h" +#include "gettext.h" struct ll_merge_driver; @@ -332,7 +335,7 @@ static int read_merge_config(const char *var, const char *value, * %X - the revision for our version * %Y - the revision for their version * - * If the file is not named indentically in all versions, then each + * If the file is not named identically in all versions, then each * revision is joined with the corresponding path, separated by a colon. * The external merge driver should write the results in the * file named by %A, and signal that it has done with zero exit @@ -425,7 +428,10 @@ enum ll_merge_result ll_merge(mmbuffer_t *result_buf, git_check_attr(istate, path, check); ll_driver_name = check->items[0].value; if (check->items[1].value) { - marker_size = atoi(check->items[1].value); + if (strtol_i(check->items[1].value, 10, &marker_size)) { + marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + warning(_("invalid marker-size '%s', expecting an integer"), check->items[1].value); + } if (marker_size <= 0) marker_size = DEFAULT_CONFLICT_MARKER_SIZE; } @@ -452,7 +458,10 @@ int ll_merge_marker_size(struct index_state *istate, const char *path) check = attr_check_initl("conflict-marker-size", NULL); git_check_attr(istate, path, check); if (check->items[0].value) { - marker_size = atoi(check->items[0].value); + if (strtol_i(check->items[0].value, 10, &marker_size)) { + marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + warning(_("invalid marker-size '%s', expecting an integer"), check->items[0].value); + } if (marker_size <= 0) marker_size = DEFAULT_CONFLICT_MARKER_SIZE; } diff --git a/merge-ort.c b/merge-ort.c index e9d01ac7f7..11029c10be 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -689,8 +689,7 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti, */ strmap_clear_func(&opti->conflicted, 0); - if (opti->attr_index.cache_nr) /* true iff opt->renormalize */ - discard_index(&opti->attr_index); + discard_index(&opti->attr_index); /* Free memory used by various renames maps */ for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) { @@ -1148,7 +1147,7 @@ static void collect_rename_info(struct merge_options *opt, * Update dir_rename_mask (determines ignore-rename-source validity) * * dir_rename_mask helps us keep track of when directory rename - * detection may be relevant. Basically, whenver a directory is + * detection may be relevant. Basically, whenever a directory is * removed on one side of history, and a file is added to that * directory on the other side of history, directory rename * detection is relevant (meaning we have to detect renames for all @@ -2711,7 +2710,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, struct conflict_info *dir_ci; char *cur_dir = dirs_to_insert.items[i].string; - CALLOC_ARRAY(dir_ci, 1); + dir_ci = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*dir_ci)); dir_ci->merged.directory_name = parent_name; len = strlen(parent_name); @@ -2839,6 +2838,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt, * Finally, record the new location. */ pair->two->path = new_path; + + string_list_clear(&dirs_to_insert, 0); } /*** Function Grouping: functions related to regular rename detection ***/ @@ -3535,7 +3536,7 @@ simple_cleanup: /* Free memory for renames->pairs[] and combined */ for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) { free(renames->pairs[s].queue); - DIFF_QUEUE_CLEAR(&renames->pairs[s]); + diff_queue_init(&renames->pairs[s]); } for (i = 0; i < combined.nr; i++) pool_diff_free_filepair(&opt->priv->pool, combined.queue[i]); @@ -3836,7 +3837,7 @@ static int write_completed_directory(struct merge_options *opt, * src/moduleB 2 * * which is used to know that xtract.c & token.txt are from the - * toplevel dirctory, while umm.c & stuff.h & baz.c are from the + * toplevel directory, while umm.c & stuff.h & baz.c are from the * src/moduleB directory. Again, following the example above, * once we need to process src/moduleB, then info->offsets is * updated to diff --git a/merge-recursive.c b/merge-recursive.c index 5cc638066a..ed64a4c537 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -3921,7 +3921,7 @@ int merge_recursive_generic(struct merge_options *opt, return clean ? 0 : 1; } -static void merge_recursive_config(struct merge_options *opt) +static void merge_recursive_config(struct merge_options *opt, int ui) { char *value = NULL; int renormalize = 0; @@ -3950,11 +3950,20 @@ static void merge_recursive_config(struct merge_options *opt) } /* avoid erroring on values from future versions of git */ free(value); } + if (ui) { + if (!git_config_get_string("diff.algorithm", &value)) { + long diff_algorithm = parse_algorithm_value(value); + if (diff_algorithm < 0) + die(_("unknown value for config '%s': %s"), "diff.algorithm", value); + opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm; + free(value); + } + } git_config(git_xmerge_config, NULL); } -void init_merge_options(struct merge_options *opt, - struct repository *repo) +static void init_merge_options(struct merge_options *opt, + struct repository *repo, int ui) { const char *merge_verbosity; memset(opt, 0, sizeof(struct merge_options)); @@ -3973,7 +3982,7 @@ void init_merge_options(struct merge_options *opt, opt->conflict_style = -1; - merge_recursive_config(opt); + merge_recursive_config(opt, ui); merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); if (merge_verbosity) opt->verbosity = strtol(merge_verbosity, NULL, 10); @@ -3981,6 +3990,18 @@ void init_merge_options(struct merge_options *opt, opt->buffer_output = 0; } +void init_ui_merge_options(struct merge_options *opt, + struct repository *repo) +{ + init_merge_options(opt, repo, 1); +} + +void init_basic_merge_options(struct merge_options *opt, + struct repository *repo) +{ + init_merge_options(opt, repo, 0); +} + /* * For now, members of merge_options do not need deep copying, but * it may change in the future, in which case we would need to update diff --git a/merge-recursive.h b/merge-recursive.h index 3136c7cc2d..0b91f28f90 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -54,7 +54,10 @@ struct merge_options { struct merge_options_internal *priv; }; -void init_merge_options(struct merge_options *opt, struct repository *repo); +/* for use by porcelain commands */ +void init_ui_merge_options(struct merge_options *opt, struct repository *repo); +/* for use by plumbing commands */ +void init_basic_merge_options(struct merge_options *opt, struct repository *repo); void copy_merge_options(struct merge_options *dst, struct merge_options *src); void clear_merge_options(struct merge_options *opt); diff --git a/mergetools/vimdiff b/mergetools/vimdiff index f8ad6b35d4..ffc9be86c8 100644 --- a/mergetools/vimdiff +++ b/mergetools/vimdiff @@ -411,7 +411,7 @@ merge_cmd () { -f "$FINAL_CMD" '"$LOCAL"' '"$BASE"' '"$REMOTE"' '"$MERGED"' else # If there is no BASE (example: a merge conflict in a new file - # with the same name created in both braches which didn't exist + # with the same name created in both branches which didn't exist # before), close all BASE windows using vim's "quit" command FINAL_CMD=$(echo "$FINAL_CMD" | \ diff --git a/mergetools/vscode b/mergetools/vscode new file mode 100644 index 0000000000..3b39b458d6 --- /dev/null +++ b/mergetools/vscode @@ -0,0 +1,19 @@ +diff_cmd () { + "$merge_tool_path" --wait --diff "$LOCAL" "$REMOTE" +} + +diff_cmd_help () { + echo "Use Visual Studio Code (requires a graphical session)" +} + +merge_cmd () { + "$merge_tool_path" --wait --merge "$REMOTE" "$LOCAL" "$BASE" "$MERGED" +} + +merge_cmd_help () { + echo "Use Visual Studio Code (requires a graphical session)" +} + +translate_merge_tool_path () { + echo code +} diff --git a/midx-write.c b/midx-write.c index a77ee73c68..bcd1d50eb0 100644 --- a/midx-write.c +++ b/midx-write.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "abspath.h" #include "config.h" @@ -17,6 +15,8 @@ #include "refs.h" #include "revision.h" #include "list-objects.h" +#include "path.h" +#include "pack-revindex.h" #define PACK_EXPIRED UINT_MAX #define BITMAP_POS_UNKNOWN (~((uint32_t)0)) @@ -25,17 +25,21 @@ extern int midx_checksum_valid(struct multi_pack_index *m); extern void clear_midx_files_ext(const char *object_dir, const char *ext, - unsigned char *keep_hash); + const char *keep_hash); +extern void clear_incremental_midx_files_ext(const char *object_dir, + const char *ext, + const char **keep_hashes, + uint32_t hashes_nr); extern int cmp_idx_or_pack_name(const char *idx_or_pack_name, const char *idx_name); -static size_t write_midx_header(struct hashfile *f, - unsigned char num_chunks, +static size_t write_midx_header(const struct git_hash_algo *hash_algo, + struct hashfile *f, unsigned char num_chunks, uint32_t num_packs) { hashwrite_be32(f, MIDX_SIGNATURE); hashwrite_u8(f, MIDX_VERSION); - hashwrite_u8(f, oid_version(the_hash_algo)); + hashwrite_u8(f, oid_version(hash_algo)); hashwrite_u8(f, num_chunks); hashwrite_u8(f, 0); /* unused */ hashwrite_be32(f, num_packs); @@ -86,6 +90,7 @@ struct write_midx_context { size_t nr; size_t alloc; struct multi_pack_index *m; + struct multi_pack_index *base_midx; struct progress *progress; unsigned pack_paths_checked; @@ -99,7 +104,12 @@ struct write_midx_context { int preferred_pack_idx; + int incremental; + uint32_t num_multi_pack_indexes_before; + struct string_list *to_include; + + struct repository *repo; }; static int should_include_pack(const struct write_midx_context *ctx, @@ -122,6 +132,9 @@ static int should_include_pack(const struct write_midx_context *ctx, */ if (ctx->m && midx_contains_pack(ctx->m, file_name)) return 0; + else if (ctx->base_midx && midx_contains_pack(ctx->base_midx, + file_name)) + return 0; else if (ctx->to_include && !string_list_has_string(ctx->to_include, file_name)) return 0; @@ -141,7 +154,7 @@ static void add_pack_to_midx(const char *full_path, size_t full_path_len, return; ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc); - p = add_packed_git(full_path, full_path_len, 0); + p = add_packed_git(ctx->repo, full_path, full_path_len, 0); if (!p) { warning(_("failed to add packfile '%s'"), full_path); @@ -196,7 +209,7 @@ static int nth_midxed_pack_midx_entry(struct multi_pack_index *m, struct pack_midx_entry *e, uint32_t pos) { - if (pos >= m->num_objects) + if (pos >= m->num_objects + m->num_objects_in_base) return 1; nth_midxed_object_oid(&e->oid, m, pos); @@ -247,12 +260,16 @@ static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout, uint32_t cur_fanout, int preferred_pack) { - uint32_t start = 0, end; + uint32_t start = m->num_objects_in_base, end; uint32_t cur_object; + if (m->base_midx) + midx_fanout_add_midx_fanout(fanout, m->base_midx, cur_fanout, + preferred_pack); + if (cur_fanout) - start = ntohl(m->chunk_oid_fanout[cur_fanout - 1]); - end = ntohl(m->chunk_oid_fanout[cur_fanout]); + start += ntohl(m->chunk_oid_fanout[cur_fanout - 1]); + end = m->num_objects_in_base + ntohl(m->chunk_oid_fanout[cur_fanout]); for (cur_object = start; cur_object < end; cur_object++) { if ((preferred_pack > -1) && @@ -334,7 +351,7 @@ static void compute_sorted_entries(struct write_midx_context *ctx, for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) { fanout.nr = 0; - if (ctx->m) + if (ctx->m && !ctx->incremental) midx_fanout_add_midx_fanout(&fanout, ctx->m, cur_fanout, ctx->preferred_pack_idx); @@ -360,6 +377,10 @@ static void compute_sorted_entries(struct write_midx_context *ctx, if (cur_object && oideq(&fanout.entries[cur_object - 1].oid, &fanout.entries[cur_object].oid)) continue; + if (ctx->incremental && ctx->base_midx && + midx_has_oid(ctx->base_midx, + &fanout.entries[cur_object].oid)) + continue; ALLOC_GROW(ctx->entries, st_add(ctx->entries_nr, 1), alloc_objects); @@ -459,7 +480,7 @@ static int write_midx_oid_lookup(struct hashfile *f, void *data) { struct write_midx_context *ctx = data; - unsigned char hash_len = the_hash_algo->rawsz; + unsigned char hash_len = ctx->repo->hash_algo->rawsz; struct pack_midx_entry *list = ctx->entries; uint32_t i; @@ -543,10 +564,16 @@ static int write_midx_revindex(struct hashfile *f, void *data) { struct write_midx_context *ctx = data; - uint32_t i; + uint32_t i, nr_base; + + if (ctx->incremental && ctx->base_midx) + nr_base = ctx->base_midx->num_objects + + ctx->base_midx->num_objects_in_base; + else + nr_base = 0; for (i = 0; i < ctx->entries_nr; i++) - hashwrite_be32(f, ctx->pack_order[i]); + hashwrite_be32(f, ctx->pack_order[i] + nr_base); return 0; } @@ -575,12 +602,18 @@ static int midx_pack_order_cmp(const void *va, const void *vb) static uint32_t *midx_pack_order(struct write_midx_context *ctx) { struct midx_pack_order_data *data; - uint32_t *pack_order; + uint32_t *pack_order, base_objects = 0; uint32_t i; - trace2_region_enter("midx", "midx_pack_order", the_repository); + trace2_region_enter("midx", "midx_pack_order", ctx->repo); + + if (ctx->incremental && ctx->base_midx) + base_objects = ctx->base_midx->num_objects + + ctx->base_midx->num_objects_in_base; + ALLOC_ARRAY(pack_order, ctx->entries_nr); ALLOC_ARRAY(data, ctx->entries_nr); + for (i = 0; i < ctx->entries_nr; i++) { struct pack_midx_entry *e = &ctx->entries[i]; data[i].nr = i; @@ -592,12 +625,11 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx) QSORT(data, ctx->entries_nr, midx_pack_order_cmp); - ALLOC_ARRAY(pack_order, ctx->entries_nr); for (i = 0; i < ctx->entries_nr; i++) { struct pack_midx_entry *e = &ctx->entries[data[i].nr]; struct pack_info *pack = &ctx->info[ctx->pack_perm[e->pack_int_id]]; if (pack->bitmap_pos == BITMAP_POS_UNKNOWN) - pack->bitmap_pos = i; + pack->bitmap_pos = i + base_objects; pack->bitmap_nr++; pack_order[i] = data[i].nr; } @@ -608,7 +640,7 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx) } free(data); - trace2_region_leave("midx", "midx_pack_order", the_repository); + trace2_region_leave("midx", "midx_pack_order", ctx->repo); return pack_order; } @@ -617,11 +649,12 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash, struct write_midx_context *ctx) { struct strbuf buf = STRBUF_INIT; - const char *tmp_file; + char *tmp_file; - trace2_region_enter("midx", "write_midx_reverse_index", the_repository); + trace2_region_enter("midx", "write_midx_reverse_index", ctx->repo); - strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex(midx_hash)); + strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex_algop(midx_hash, + ctx->repo->hash_algo)); tmp_file = write_rev_file_order(NULL, ctx->pack_order, ctx->entries_nr, midx_hash, WRITE_REV); @@ -630,8 +663,9 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash, die(_("cannot store reverse index file")); strbuf_release(&buf); + free(tmp_file); - trace2_region_leave("midx", "write_midx_reverse_index", the_repository); + trace2_region_leave("midx", "write_midx_reverse_index", ctx->repo); } static void prepare_midx_packing_data(struct packing_data *pdata, @@ -639,23 +673,24 @@ static void prepare_midx_packing_data(struct packing_data *pdata, { uint32_t i; - trace2_region_enter("midx", "prepare_midx_packing_data", the_repository); + trace2_region_enter("midx", "prepare_midx_packing_data", ctx->repo); memset(pdata, 0, sizeof(struct packing_data)); - prepare_packing_data(the_repository, pdata); + prepare_packing_data(ctx->repo, pdata); for (i = 0; i < ctx->entries_nr; i++) { - struct pack_midx_entry *from = &ctx->entries[ctx->pack_order[i]]; + uint32_t pos = ctx->pack_order[i]; + struct pack_midx_entry *from = &ctx->entries[pos]; struct object_entry *to = packlist_alloc(pdata, &from->oid); oe_set_in_pack(pdata, to, ctx->info[ctx->pack_perm[from->pack_int_id]].p); } - trace2_region_leave("midx", "prepare_midx_packing_data", the_repository); + trace2_region_leave("midx", "prepare_midx_packing_data", ctx->repo); } -static int add_ref_to_pending(const char *refname, +static int add_ref_to_pending(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { @@ -668,7 +703,7 @@ static int add_ref_to_pending(const char *refname, return 0; } - if (!peel_iterated_oid(the_repository, oid, &peeled)) + if (!peel_iterated_oid(revs->repo, oid, &peeled)) oid = &peeled; object = parse_object_or_die(oid, refname); @@ -726,7 +761,7 @@ static int read_refs_snapshot(const char *refs_snapshot, hex = &buf.buf[1]; } - if (parse_oid_hex(hex, &oid, &end) < 0) + if (parse_oid_hex_algop(hex, &oid, &end, revs->repo->hash_algo) < 0) die(_("could not parse line: %s"), buf.buf); if (*end) die(_("malformed line: %s"), buf.buf); @@ -742,6 +777,7 @@ static int read_refs_snapshot(const char *refs_snapshot, strbuf_release(&buf); return 0; } + static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr_p, const char *refs_snapshot, struct write_midx_context *ctx) @@ -749,17 +785,16 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr struct rev_info revs; struct bitmap_commit_cb cb = {0}; - trace2_region_enter("midx", "find_commits_for_midx_bitmap", - the_repository); + trace2_region_enter("midx", "find_commits_for_midx_bitmap", ctx->repo); cb.ctx = ctx; - repo_init_revisions(the_repository, &revs, NULL); + repo_init_revisions(ctx->repo, &revs, NULL); if (refs_snapshot) { read_refs_snapshot(refs_snapshot, &revs); } else { setup_revisions(0, NULL, &revs, NULL); - refs_for_each_ref(get_main_ref_store(the_repository), + refs_for_each_ref(get_main_ref_store(ctx->repo), add_ref_to_pending, &revs); } @@ -787,13 +822,12 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr release_revisions(&revs); - trace2_region_leave("midx", "find_commits_for_midx_bitmap", - the_repository); + trace2_region_leave("midx", "find_commits_for_midx_bitmap", ctx->repo); return cb.commits; } -static int write_midx_bitmap(const char *midx_name, +static int write_midx_bitmap(struct repository *r, const char *midx_name, const unsigned char *midx_hash, struct packing_data *pdata, struct commit **commits, @@ -806,9 +840,9 @@ static int write_midx_bitmap(const char *midx_name, struct bitmap_writer writer; struct pack_idx_entry **index; char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name, - hash_to_hex(midx_hash)); + hash_to_hex_algop(midx_hash, r->hash_algo)); - trace2_region_enter("midx", "write_midx_bitmap", the_repository); + trace2_region_enter("midx", "write_midx_bitmap", r); if (flags & MIDX_WRITE_BITMAP_HASH_CACHE) options |= BITMAP_OPT_HASH_CACHE; @@ -825,10 +859,9 @@ static int write_midx_bitmap(const char *midx_name, for (i = 0; i < pdata->nr_objects; i++) index[i] = &pdata->objects[i].idx; - bitmap_writer_init(&writer, the_repository); + bitmap_writer_init(&writer, r, pdata); bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS); - bitmap_writer_build_type_index(&writer, pdata, index, - pdata->nr_objects); + bitmap_writer_build_type_index(&writer, index); /* * bitmap_writer_finish expects objects in lex order, but pack_order @@ -847,20 +880,19 @@ static int write_midx_bitmap(const char *midx_name, index[pack_order[i]] = &pdata->objects[i].idx; bitmap_writer_select_commits(&writer, commits, commits_nr); - ret = bitmap_writer_build(&writer, pdata); + ret = bitmap_writer_build(&writer); if (ret < 0) goto cleanup; bitmap_writer_set_checksum(&writer, midx_hash); - bitmap_writer_finish(&writer, index, pdata->nr_objects, bitmap_name, - options); + bitmap_writer_finish(&writer, index, bitmap_name, options); cleanup: free(index); free(bitmap_name); bitmap_writer_free(&writer); - trace2_region_leave("midx", "write_midx_bitmap", the_repository); + trace2_region_leave("midx", "write_midx_bitmap", r); return ret; } @@ -893,38 +925,131 @@ cleanup: static int fill_packs_from_midx(struct write_midx_context *ctx, const char *preferred_pack_name, uint32_t flags) { - uint32_t i; + struct multi_pack_index *m; - for (i = 0; i < ctx->m->num_packs; i++) { - ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc); + for (m = ctx->m; m; m = m->base_midx) { + uint32_t i; + + for (i = 0; i < m->num_packs; i++) { + ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc); - if (flags & MIDX_WRITE_REV_INDEX || preferred_pack_name) { /* * If generating a reverse index, need to have * packed_git's loaded to compare their * mtimes and object count. * - * * If a preferred pack is specified, need to * have packed_git's loaded to ensure the chosen * preferred pack has a non-zero object count. */ - if (prepare_midx_pack(the_repository, ctx->m, i)) - return error(_("could not load pack")); + if (flags & MIDX_WRITE_REV_INDEX || + preferred_pack_name) { + if (prepare_midx_pack(ctx->repo, m, + m->num_packs_in_base + i)) { + error(_("could not load pack")); + return 1; + } + + if (open_pack_index(m->packs[i])) + die(_("could not open index for %s"), + m->packs[i]->pack_name); + } - if (open_pack_index(ctx->m->packs[i])) - die(_("could not open index for %s"), - ctx->m->packs[i]->pack_name); + fill_pack_info(&ctx->info[ctx->nr++], m->packs[i], + m->pack_names[i], + m->num_packs_in_base + i); } + } + return 0; +} + +static struct { + const char *non_split; + const char *split; +} midx_exts[] = { + {NULL, MIDX_EXT_MIDX}, + {MIDX_EXT_BITMAP, MIDX_EXT_BITMAP}, + {MIDX_EXT_REV, MIDX_EXT_REV}, +}; + +static int link_midx_to_chain(struct multi_pack_index *m) +{ + struct strbuf from = STRBUF_INIT; + struct strbuf to = STRBUF_INIT; + int ret = 0; + size_t i; - fill_pack_info(&ctx->info[ctx->nr++], ctx->m->packs[i], - ctx->m->pack_names[i], i); + if (!m || m->has_chain) { + /* + * Either no MIDX previously existed, or it was already + * part of a MIDX chain. In both cases, we have nothing + * to link, so return early. + */ + goto done; } - return 0; + for (i = 0; i < ARRAY_SIZE(midx_exts); i++) { + const unsigned char *hash = get_midx_checksum(m); + + get_midx_filename_ext(m->repo->hash_algo, &from, m->object_dir, + hash, midx_exts[i].non_split); + get_split_midx_filename_ext(m->repo->hash_algo, &to, + m->object_dir, hash, + midx_exts[i].split); + + if (link(from.buf, to.buf) < 0 && errno != ENOENT) { + ret = error_errno(_("unable to link '%s' to '%s'"), + from.buf, to.buf); + goto done; + } + + strbuf_reset(&from); + strbuf_reset(&to); + } + +done: + strbuf_release(&from); + strbuf_release(&to); + return ret; +} + +static void clear_midx_files(struct repository *r, const char *object_dir, + const char **hashes, uint32_t hashes_nr, + unsigned incremental) +{ + /* + * if incremental: + * - remove all non-incremental MIDX files + * - remove any incremental MIDX files not in the current one + * + * if non-incremental: + * - remove all incremental MIDX files + * - remove any non-incremental MIDX files not matching the current + * hash + */ + struct strbuf buf = STRBUF_INIT; + const char *exts[] = { MIDX_EXT_BITMAP, MIDX_EXT_REV, MIDX_EXT_MIDX }; + uint32_t i, j; + + for (i = 0; i < ARRAY_SIZE(exts); i++) { + clear_incremental_midx_files_ext(object_dir, exts[i], + hashes, hashes_nr); + for (j = 0; j < hashes_nr; j++) + clear_midx_files_ext(object_dir, exts[i], hashes[j]); + } + + if (incremental) + get_midx_filename(r->hash_algo, &buf, object_dir); + else + get_midx_chain_filename(&buf, object_dir); + + if (unlink(buf.buf) && errno != ENOENT) + die_errno(_("failed to clear multi-pack-index at %s"), buf.buf); + + strbuf_release(&buf); } -static int write_midx_internal(const char *object_dir, +static int write_midx_internal(struct repository *r, const char *object_dir, struct string_list *packs_to_include, struct string_list *packs_to_drop, const char *preferred_pack_name, @@ -936,42 +1061,67 @@ static int write_midx_internal(const char *object_dir, uint32_t i, start_pack; struct hashfile *f = NULL; struct lock_file lk; + struct tempfile *incr; struct write_midx_context ctx = { 0 }; int bitmapped_packs_concat_len = 0; int pack_name_concat_len = 0; int dropped_packs = 0; int result = 0; + const char **keep_hashes = NULL; struct chunkfile *cf; - trace2_region_enter("midx", "write_midx_internal", the_repository); + trace2_region_enter("midx", "write_midx_internal", r); - get_midx_filename(&midx_name, object_dir); + ctx.repo = r; + + ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL); + if (ctx.incremental && (flags & MIDX_WRITE_BITMAP)) + die(_("cannot write incremental MIDX with bitmap")); + + if (ctx.incremental) + strbuf_addf(&midx_name, + "%s/pack/multi-pack-index.d/tmp_midx_XXXXXX", + object_dir); + else + get_midx_filename(r->hash_algo, &midx_name, object_dir); if (safe_create_leading_directories(midx_name.buf)) die_errno(_("unable to create leading directories of %s"), midx_name.buf); - if (!packs_to_include) { - /* - * Only reference an existing MIDX when not filtering which - * packs to include, since all packs and objects are copied - * blindly from an existing MIDX if one is present. - */ - ctx.m = lookup_multi_pack_index(the_repository, object_dir); - } + if (!packs_to_include || ctx.incremental) { + struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir); + if (m && !midx_checksum_valid(m)) { + warning(_("ignoring existing multi-pack-index; checksum mismatch")); + m = NULL; + } - if (ctx.m && !midx_checksum_valid(ctx.m)) { - warning(_("ignoring existing multi-pack-index; checksum mismatch")); - ctx.m = NULL; + if (m) { + /* + * Only reference an existing MIDX when not filtering + * which packs to include, since all packs and objects + * are copied blindly from an existing MIDX if one is + * present. + */ + if (ctx.incremental) + ctx.base_midx = m; + else if (!packs_to_include) + ctx.m = m; + } } ctx.nr = 0; - ctx.alloc = ctx.m ? ctx.m->num_packs : 16; + ctx.alloc = ctx.m ? ctx.m->num_packs + ctx.m->num_packs_in_base : 16; ctx.info = NULL; ALLOC_ARRAY(ctx.info, ctx.alloc); - if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name, - flags) < 0) { - result = 1; + if (ctx.incremental) { + struct multi_pack_index *m = ctx.base_midx; + while (m) { + ctx.num_multi_pack_indexes_before++; + m = m->base_midx; + } + } else if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name, + flags) < 0) { goto cleanup; } @@ -988,7 +1138,8 @@ static int write_midx_internal(const char *object_dir, for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx); stop_progress(&ctx.progress); - if ((ctx.m && ctx.nr == ctx.m->num_packs) && + if ((ctx.m && ctx.nr == ctx.m->num_packs + ctx.m->num_packs_in_base) && + !ctx.incremental && !(packs_to_include || packs_to_drop)) { struct bitmap_index *bitmap_git; int bitmap_exists; @@ -1004,12 +1155,14 @@ static int write_midx_internal(const char *object_dir, * corresponding bitmap (or one wasn't requested). */ if (!want_bitmap) - clear_midx_files_ext(object_dir, ".bitmap", - NULL); + clear_midx_files_ext(object_dir, "bitmap", NULL); goto cleanup; } } + if (ctx.incremental && !ctx.nr) + goto cleanup; /* nothing to do */ + if (preferred_pack_name) { ctx.preferred_pack_idx = -1; @@ -1155,9 +1308,6 @@ static int write_midx_internal(const char *object_dir, pack_name_concat_len += MIDX_CHUNK_ALIGNMENT - (pack_name_concat_len % MIDX_CHUNK_ALIGNMENT); - hold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR); - f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk)); - if (ctx.nr - dropped_packs == 0) { error(_("no pack files to index.")); result = 1; @@ -1170,6 +1320,31 @@ static int write_midx_internal(const char *object_dir, flags &= ~(MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP); } + if (ctx.incremental) { + struct strbuf lock_name = STRBUF_INIT; + + get_midx_chain_filename(&lock_name, object_dir); + hold_lock_file_for_update(&lk, lock_name.buf, LOCK_DIE_ON_ERROR); + strbuf_release(&lock_name); + + incr = mks_tempfile_m(midx_name.buf, 0444); + if (!incr) { + error(_("unable to create temporary MIDX layer")); + return -1; + } + + if (adjust_shared_perm(get_tempfile_path(incr))) { + error(_("unable to adjust shared permissions for '%s'"), + get_tempfile_path(incr)); + return -1; + } + + f = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr)); + } else { + hold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR); + f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk)); + } + cf = init_chunkfile(f); add_chunk(cf, MIDX_CHUNKID_PACKNAMES, pack_name_concat_len, @@ -1177,7 +1352,7 @@ static int write_midx_internal(const char *object_dir, add_chunk(cf, MIDX_CHUNKID_OIDFANOUT, MIDX_CHUNK_FANOUT_SIZE, write_midx_oid_fanout); add_chunk(cf, MIDX_CHUNKID_OIDLOOKUP, - st_mult(ctx.entries_nr, the_hash_algo->rawsz), + st_mult(ctx.entries_nr, r->hash_algo->rawsz), write_midx_oid_lookup); add_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, st_mult(ctx.entries_nr, MIDX_CHUNK_OFFSET_WIDTH), @@ -1199,7 +1374,8 @@ static int write_midx_internal(const char *object_dir, write_midx_bitmapped_packs); } - write_midx_header(f, get_num_chunks(cf), ctx.nr - dropped_packs); + write_midx_header(r->hash_algo, f, get_num_chunks(cf), + ctx.nr - dropped_packs); write_chunkfile(cf, &ctx); finalize_hashfile(f, midx_hash, FSYNC_COMPONENT_PACK_METADATA, @@ -1231,7 +1407,7 @@ static int write_midx_internal(const char *object_dir, FREE_AND_NULL(ctx.entries); ctx.entries_nr = 0; - if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata, + if (write_midx_bitmap(r, midx_name.buf, midx_hash, &pdata, commits, commits_nr, ctx.pack_order, flags) < 0) { error(_("could not write multi-pack bitmap")); @@ -1249,14 +1425,58 @@ static int write_midx_internal(const char *object_dir, * have been freed in the previous if block. */ - if (ctx.m) - close_object_store(the_repository->objects); + CALLOC_ARRAY(keep_hashes, ctx.num_multi_pack_indexes_before + 1); + + if (ctx.incremental) { + FILE *chainf = fdopen_lock_file(&lk, "w"); + struct strbuf final_midx_name = STRBUF_INIT; + struct multi_pack_index *m = ctx.base_midx; + + if (!chainf) { + error_errno(_("unable to open multi-pack-index chain file")); + return -1; + } + + if (link_midx_to_chain(ctx.base_midx) < 0) + return -1; + + get_split_midx_filename_ext(r->hash_algo, &final_midx_name, + object_dir, midx_hash, MIDX_EXT_MIDX); + + if (rename_tempfile(&incr, final_midx_name.buf) < 0) { + error_errno(_("unable to rename new multi-pack-index layer")); + return -1; + } + + strbuf_release(&final_midx_name); + + keep_hashes[ctx.num_multi_pack_indexes_before] = + xstrdup(hash_to_hex_algop(midx_hash, r->hash_algo)); + + for (i = 0; i < ctx.num_multi_pack_indexes_before; i++) { + uint32_t j = ctx.num_multi_pack_indexes_before - i - 1; + + keep_hashes[j] = xstrdup(hash_to_hex_algop(get_midx_checksum(m), + r->hash_algo)); + m = m->base_midx; + } + + for (i = 0; i < ctx.num_multi_pack_indexes_before + 1; i++) + fprintf(get_lock_file_fp(&lk), "%s\n", keep_hashes[i]); + } else { + keep_hashes[ctx.num_multi_pack_indexes_before] = + xstrdup(hash_to_hex_algop(midx_hash, r->hash_algo)); + } + + if (ctx.m || ctx.base_midx) + close_object_store(ctx.repo->objects); if (commit_lock_file(&lk) < 0) die_errno(_("could not write multi-pack-index")); - clear_midx_files_ext(object_dir, ".bitmap", midx_hash); - clear_midx_files_ext(object_dir, ".rev", midx_hash); + clear_midx_files(r, object_dir, keep_hashes, + ctx.num_multi_pack_indexes_before + 1, + ctx.incremental); cleanup: for (i = 0; i < ctx.nr; i++) { @@ -1271,29 +1491,33 @@ cleanup: free(ctx.entries); free(ctx.pack_perm); free(ctx.pack_order); + if (keep_hashes) { + for (i = 0; i < ctx.num_multi_pack_indexes_before + 1; i++) + free((char *)keep_hashes[i]); + free(keep_hashes); + } strbuf_release(&midx_name); - trace2_region_leave("midx", "write_midx_internal", the_repository); + trace2_region_leave("midx", "write_midx_internal", r); return result; } -int write_midx_file(const char *object_dir, +int write_midx_file(struct repository *r, const char *object_dir, const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags) + const char *refs_snapshot, unsigned flags) { - return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name, - refs_snapshot, flags); + return write_midx_internal(r, object_dir, NULL, NULL, + preferred_pack_name, refs_snapshot, + flags); } -int write_midx_file_only(const char *object_dir, +int write_midx_file_only(struct repository *r, const char *object_dir, struct string_list *packs_to_include, const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags) + const char *refs_snapshot, unsigned flags) { - return write_midx_internal(object_dir, packs_to_include, NULL, + return write_midx_internal(r, object_dir, packs_to_include, NULL, preferred_pack_name, refs_snapshot, flags); } @@ -1307,6 +1531,9 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla if (!m) return 0; + if (m->base_midx) + die(_("cannot expire packs from an incremental multi-pack-index")); + CALLOC_ARRAY(count, m->num_packs); if (flags & MIDX_PROGRESS) @@ -1347,7 +1574,8 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla free(count); if (packs_to_drop.nr) - result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, NULL, flags); + result = write_midx_internal(r, object_dir, NULL, + &packs_to_drop, NULL, NULL, flags); string_list_clear(&packs_to_drop, 0); @@ -1481,6 +1709,8 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, if (!m) return 0; + if (m->base_midx) + die(_("cannot repack an incremental multi-pack-index")); CALLOC_ARRAY(include_pack, m->num_packs); @@ -1542,7 +1772,8 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, goto cleanup; } - result = write_midx_internal(object_dir, NULL, NULL, NULL, NULL, flags); + result = write_midx_internal(r, object_dir, NULL, NULL, NULL, NULL, + flags); cleanup: free(include_pack); @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "config.h" #include "dir.h" @@ -16,26 +14,31 @@ int midx_checksum_valid(struct multi_pack_index *m); void clear_midx_files_ext(const char *object_dir, const char *ext, - unsigned char *keep_hash); + const char *keep_hash); +void clear_incremental_midx_files_ext(const char *object_dir, const char *ext, + char **keep_hashes, + uint32_t hashes_nr); int cmp_idx_or_pack_name(const char *idx_or_pack_name, const char *idx_name); const unsigned char *get_midx_checksum(struct multi_pack_index *m) { - return m->data + m->data_len - the_hash_algo->rawsz; + return m->data + m->data_len - m->repo->hash_algo->rawsz; } -void get_midx_filename(struct strbuf *out, const char *object_dir) +void get_midx_filename(const struct git_hash_algo *hash_algo, + struct strbuf *out, const char *object_dir) { - get_midx_filename_ext(out, object_dir, NULL, NULL); + get_midx_filename_ext(hash_algo, out, object_dir, NULL, NULL); } -void get_midx_filename_ext(struct strbuf *out, const char *object_dir, +void get_midx_filename_ext(const struct git_hash_algo *hash_algo, + struct strbuf *out, const char *object_dir, const unsigned char *hash, const char *ext) { strbuf_addf(out, "%s/pack/multi-pack-index", object_dir); if (ext) - strbuf_addf(out, "-%s.%s", hash_to_hex(hash), ext); + strbuf_addf(out, "-%s.%s", hash_to_hex_algop(hash, hash_algo), ext); } static int midx_read_oid_fanout(const unsigned char *chunk_start, @@ -89,9 +92,10 @@ static int midx_read_object_offsets(const unsigned char *chunk_start, return 0; } -#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + the_hash_algo->rawsz) - -struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local) +static struct multi_pack_index *load_multi_pack_index_one(struct repository *r, + const char *object_dir, + const char *midx_name, + int local) { struct multi_pack_index *m = NULL; int fd; @@ -99,31 +103,26 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local size_t midx_size; void *midx_map = NULL; uint32_t hash_version; - struct strbuf midx_name = STRBUF_INIT; uint32_t i; const char *cur_pack_name; struct chunkfile *cf = NULL; - get_midx_filename(&midx_name, object_dir); - - fd = git_open(midx_name.buf); + fd = git_open(midx_name); if (fd < 0) goto cleanup_fail; if (fstat(fd, &st)) { - error_errno(_("failed to read %s"), midx_name.buf); + error_errno(_("failed to read %s"), midx_name); goto cleanup_fail; } midx_size = xsize_t(st.st_size); - if (midx_size < MIDX_MIN_SIZE) { - error(_("multi-pack-index file %s is too small"), midx_name.buf); + if (midx_size < (MIDX_HEADER_SIZE + r->hash_algo->rawsz)) { + error(_("multi-pack-index file %s is too small"), midx_name); goto cleanup_fail; } - strbuf_release(&midx_name); - midx_map = xmmap(NULL, midx_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); @@ -131,6 +130,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local m->data = midx_map; m->data_len = midx_size; m->local = local; + m->repo = r; m->signature = get_be32(m->data); if (m->signature != MIDX_SIGNATURE) @@ -143,12 +143,12 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local m->version); hash_version = m->data[MIDX_BYTE_HASH_VERSION]; - if (hash_version != oid_version(the_hash_algo)) { + if (hash_version != oid_version(r->hash_algo)) { error(_("multi-pack-index hash version %u does not match version %u"), - hash_version, oid_version(the_hash_algo)); + hash_version, oid_version(r->hash_algo)); goto cleanup_fail; } - m->hash_len = the_hash_algo->rawsz; + m->hash_len = r->hash_algo->rawsz; m->num_chunks = m->data[MIDX_BYTE_NUM_CHUNKS]; @@ -205,15 +205,14 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local m->pack_names[i]); } - trace2_data_intmax("midx", the_repository, "load/num_packs", m->num_packs); - trace2_data_intmax("midx", the_repository, "load/num_objects", m->num_objects); + trace2_data_intmax("midx", r, "load/num_packs", m->num_packs); + trace2_data_intmax("midx", r, "load/num_objects", m->num_objects); free_chunkfile(cf); return m; cleanup_fail: free(m); - strbuf_release(&midx_name); free_chunkfile(cf); if (midx_map) munmap(midx_map, midx_size); @@ -222,6 +221,176 @@ cleanup_fail: return NULL; } +void get_midx_chain_dirname(struct strbuf *buf, const char *object_dir) +{ + strbuf_addf(buf, "%s/pack/multi-pack-index.d", object_dir); +} + +void get_midx_chain_filename(struct strbuf *buf, const char *object_dir) +{ + get_midx_chain_dirname(buf, object_dir); + strbuf_addstr(buf, "/multi-pack-index-chain"); +} + +void get_split_midx_filename_ext(const struct git_hash_algo *hash_algo, + struct strbuf *buf, const char *object_dir, + const unsigned char *hash, const char *ext) +{ + get_midx_chain_dirname(buf, object_dir); + strbuf_addf(buf, "/multi-pack-index-%s.%s", + hash_to_hex_algop(hash, hash_algo), ext); +} + +static int open_multi_pack_index_chain(const struct git_hash_algo *hash_algo, + const char *chain_file, int *fd, + struct stat *st) +{ + *fd = git_open(chain_file); + if (*fd < 0) + return 0; + if (fstat(*fd, st)) { + close(*fd); + return 0; + } + if (st->st_size < hash_algo->hexsz) { + close(*fd); + if (!st->st_size) { + /* treat empty files the same as missing */ + errno = ENOENT; + } else { + warning(_("multi-pack-index chain file too small")); + errno = EINVAL; + } + return 0; + } + return 1; +} + +static int add_midx_to_chain(struct multi_pack_index *midx, + struct multi_pack_index *midx_chain) +{ + if (midx_chain) { + if (unsigned_add_overflows(midx_chain->num_packs, + midx_chain->num_packs_in_base)) { + warning(_("pack count in base MIDX too high: %"PRIuMAX), + (uintmax_t)midx_chain->num_packs_in_base); + return 0; + } + if (unsigned_add_overflows(midx_chain->num_objects, + midx_chain->num_objects_in_base)) { + warning(_("object count in base MIDX too high: %"PRIuMAX), + (uintmax_t)midx_chain->num_objects_in_base); + return 0; + } + midx->num_packs_in_base = midx_chain->num_packs + + midx_chain->num_packs_in_base; + midx->num_objects_in_base = midx_chain->num_objects + + midx_chain->num_objects_in_base; + } + + midx->base_midx = midx_chain; + midx->has_chain = 1; + + return 1; +} + +static struct multi_pack_index *load_midx_chain_fd_st(struct repository *r, + const char *object_dir, + int local, + int fd, struct stat *st, + int *incomplete_chain) +{ + struct multi_pack_index *midx_chain = NULL; + struct strbuf buf = STRBUF_INIT; + int valid = 1; + uint32_t i, count; + FILE *fp = xfdopen(fd, "r"); + + count = st->st_size / (r->hash_algo->hexsz + 1); + + for (i = 0; i < count; i++) { + struct multi_pack_index *m; + struct object_id layer; + + if (strbuf_getline_lf(&buf, fp) == EOF) + break; + + if (get_oid_hex_algop(buf.buf, &layer, r->hash_algo)) { + warning(_("invalid multi-pack-index chain: line '%s' " + "not a hash"), + buf.buf); + valid = 0; + break; + } + + valid = 0; + + strbuf_reset(&buf); + get_split_midx_filename_ext(r->hash_algo, &buf, object_dir, + layer.hash, MIDX_EXT_MIDX); + m = load_multi_pack_index_one(r, object_dir, buf.buf, local); + + if (m) { + if (add_midx_to_chain(m, midx_chain)) { + midx_chain = m; + valid = 1; + } else { + close_midx(m); + } + } + if (!valid) { + warning(_("unable to find all multi-pack index files")); + break; + } + } + + fclose(fp); + strbuf_release(&buf); + + *incomplete_chain = !valid; + return midx_chain; +} + +static struct multi_pack_index *load_multi_pack_index_chain(struct repository *r, + const char *object_dir, + int local) +{ + struct strbuf chain_file = STRBUF_INIT; + struct stat st; + int fd; + struct multi_pack_index *m = NULL; + + get_midx_chain_filename(&chain_file, object_dir); + if (open_multi_pack_index_chain(r->hash_algo, chain_file.buf, &fd, &st)) { + int incomplete; + /* ownership of fd is taken over by load function */ + m = load_midx_chain_fd_st(r, object_dir, local, fd, &st, + &incomplete); + } + + strbuf_release(&chain_file); + return m; +} + +struct multi_pack_index *load_multi_pack_index(struct repository *r, + const char *object_dir, + int local) +{ + struct strbuf midx_name = STRBUF_INIT; + struct multi_pack_index *m; + + get_midx_filename(r->hash_algo, &midx_name, object_dir); + + m = load_multi_pack_index_one(r, object_dir, + midx_name.buf, local); + if (!m) + m = load_multi_pack_index_chain(r, object_dir, local); + + strbuf_release(&midx_name); + + return m; +} + void close_midx(struct multi_pack_index *m) { uint32_t i; @@ -230,6 +399,7 @@ void close_midx(struct multi_pack_index *m) return; close_midx(m->next); + close_midx(m->base_midx); munmap((unsigned char *)m->data, m->data_len); @@ -242,14 +412,50 @@ void close_midx(struct multi_pack_index *m) free(m); } -int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id) +static uint32_t midx_for_object(struct multi_pack_index **_m, uint32_t pos) +{ + struct multi_pack_index *m = *_m; + while (m && pos < m->num_objects_in_base) + m = m->base_midx; + + if (!m) + BUG("NULL multi-pack-index for object position: %"PRIu32, pos); + + if (pos >= m->num_objects + m->num_objects_in_base) + die(_("invalid MIDX object position, MIDX is likely corrupt")); + + *_m = m; + + return pos - m->num_objects_in_base; +} + +static uint32_t midx_for_pack(struct multi_pack_index **_m, + uint32_t pack_int_id) +{ + struct multi_pack_index *m = *_m; + while (m && pack_int_id < m->num_packs_in_base) + m = m->base_midx; + + if (!m) + BUG("NULL multi-pack-index for pack ID: %"PRIu32, pack_int_id); + + if (pack_int_id >= m->num_packs + m->num_packs_in_base) + die(_("bad pack-int-id: %u (%u total packs)"), + pack_int_id, m->num_packs + m->num_packs_in_base); + + *_m = m; + + return pack_int_id - m->num_packs_in_base; +} + +int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, + uint32_t pack_int_id) { struct strbuf pack_name = STRBUF_INIT; + struct strbuf key = STRBUF_INIT; struct packed_git *p; - if (pack_int_id >= m->num_packs) - die(_("bad pack-int-id: %u (%u total packs)"), - pack_int_id, m->num_packs); + pack_int_id = midx_for_pack(&m, pack_int_id); if (m->packs[pack_int_id]) return 0; @@ -257,57 +463,101 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir, m->pack_names[pack_int_id]); - p = add_packed_git(pack_name.buf, pack_name.len, m->local); + /* pack_map holds the ".pack" name, but we have the .idx */ + strbuf_addbuf(&key, &pack_name); + strbuf_strip_suffix(&key, ".idx"); + strbuf_addstr(&key, ".pack"); + p = hashmap_get_entry_from_hash(&r->objects->pack_map, + strhash(key.buf), key.buf, + struct packed_git, packmap_ent); + if (!p) { + p = add_packed_git(r, pack_name.buf, pack_name.len, m->local); + if (p) { + install_packed_git(r, p); + list_add_tail(&p->mru, &r->objects->packed_git_mru); + } + } + strbuf_release(&pack_name); + strbuf_release(&key); if (!p) return 1; p->multi_pack_index = 1; m->packs[pack_int_id] = p; - install_packed_git(r, p); - list_add_tail(&p->mru, &r->objects->packed_git_mru); return 0; } +struct packed_git *nth_midxed_pack(struct multi_pack_index *m, + uint32_t pack_int_id) +{ + uint32_t local_pack_int_id = midx_for_pack(&m, pack_int_id); + return m->packs[local_pack_int_id]; +} + #define MIDX_CHUNK_BITMAPPED_PACKS_WIDTH (2 * sizeof(uint32_t)) int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m, struct bitmapped_pack *bp, uint32_t pack_int_id) { + uint32_t local_pack_int_id = midx_for_pack(&m, pack_int_id); + if (!m->chunk_bitmapped_packs) return error(_("MIDX does not contain the BTMP chunk")); if (prepare_midx_pack(r, m, pack_int_id)) return error(_("could not load bitmapped pack %"PRIu32), pack_int_id); - bp->p = m->packs[pack_int_id]; + bp->p = m->packs[local_pack_int_id]; bp->bitmap_pos = get_be32((char *)m->chunk_bitmapped_packs + - MIDX_CHUNK_BITMAPPED_PACKS_WIDTH * pack_int_id); + MIDX_CHUNK_BITMAPPED_PACKS_WIDTH * local_pack_int_id); bp->bitmap_nr = get_be32((char *)m->chunk_bitmapped_packs + - MIDX_CHUNK_BITMAPPED_PACKS_WIDTH * pack_int_id + + MIDX_CHUNK_BITMAPPED_PACKS_WIDTH * local_pack_int_id + sizeof(uint32_t)); bp->pack_int_id = pack_int_id; + bp->from_midx = m; + + return 0; +} +int bsearch_one_midx(const struct object_id *oid, struct multi_pack_index *m, + uint32_t *result) +{ + int ret = bsearch_hash(oid->hash, m->chunk_oid_fanout, + m->chunk_oid_lookup, m->repo->hash_algo->rawsz, + result); + if (result) + *result += m->num_objects_in_base; + return ret; +} + +int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, + uint32_t *result) +{ + for (; m; m = m->base_midx) + if (bsearch_one_midx(oid, m, result)) + return 1; return 0; } -int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result) +int midx_has_oid(struct multi_pack_index *m, const struct object_id *oid) { - return bsearch_hash(oid->hash, m->chunk_oid_fanout, m->chunk_oid_lookup, - the_hash_algo->rawsz, result); + return bsearch_midx(oid, m, NULL); } struct object_id *nth_midxed_object_oid(struct object_id *oid, struct multi_pack_index *m, uint32_t n) { - if (n >= m->num_objects) + if (n >= m->num_objects + m->num_objects_in_base) return NULL; + n = midx_for_object(&m, n); + oidread(oid, m->chunk_oid_lookup + st_mult(m->hash_len, n), - the_repository->hash_algo); + m->repo->hash_algo); return oid; } @@ -316,6 +566,8 @@ off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos) const unsigned char *offset_data; uint32_t offset32; + pos = midx_for_object(&m, pos); + offset_data = m->chunk_object_offsets + (off_t)pos * MIDX_CHUNK_OFFSET_WIDTH; offset32 = get_be32(offset_data + sizeof(uint32_t)); @@ -334,8 +586,10 @@ off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos) uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos) { - return get_be32(m->chunk_object_offsets + - (off_t)pos * MIDX_CHUNK_OFFSET_WIDTH); + pos = midx_for_object(&m, pos); + + return m->num_packs_in_base + get_be32(m->chunk_object_offsets + + (off_t)pos * MIDX_CHUNK_OFFSET_WIDTH); } int fill_midx_entry(struct repository *r, @@ -350,14 +604,12 @@ int fill_midx_entry(struct repository *r, if (!bsearch_midx(oid, m, &pos)) return 0; - if (pos >= m->num_objects) - return 0; - + midx_for_object(&m, pos); pack_int_id = nth_midxed_pack_int_id(m, pos); if (prepare_midx_pack(r, m, pack_int_id)) return 0; - p = m->packs[pack_int_id]; + p = m->packs[pack_int_id - m->num_packs_in_base]; /* * We are about to tell the caller where they can locate the @@ -411,8 +663,8 @@ int cmp_idx_or_pack_name(const char *idx_or_pack_name, return strcmp(idx_or_pack_name, idx_name); } -int midx_locate_pack(struct multi_pack_index *m, const char *idx_or_pack_name, - uint32_t *pos) +static int midx_contains_pack_1(struct multi_pack_index *m, + const char *idx_or_pack_name) { uint32_t first = 0, last = m->num_packs; @@ -423,11 +675,8 @@ int midx_locate_pack(struct multi_pack_index *m, const char *idx_or_pack_name, current = m->pack_names[mid]; cmp = cmp_idx_or_pack_name(idx_or_pack_name, current); - if (!cmp) { - if (pos) - *pos = mid; + if (!cmp) return 1; - } if (cmp > 0) { first = mid + 1; continue; @@ -440,19 +689,25 @@ int midx_locate_pack(struct multi_pack_index *m, const char *idx_or_pack_name, int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name) { - return midx_locate_pack(m, idx_or_pack_name, NULL); + for (; m; m = m->base_midx) + if (midx_contains_pack_1(m, idx_or_pack_name)) + return 1; + return 0; } int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id) { if (m->preferred_pack_idx == -1) { + uint32_t midx_pos; if (load_midx_revindex(m) < 0) { m->preferred_pack_idx = -2; return -1; } - m->preferred_pack_idx = - nth_midxed_pack_int_id(m, pack_pos_to_midx(m, 0)); + midx_pos = pack_pos_to_midx(m, m->num_objects_in_base); + + m->preferred_pack_idx = nth_midxed_pack_int_id(m, midx_pos); + } else if (m->preferred_pack_idx == -2) return -1; /* no revindex */ @@ -473,7 +728,7 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i if (!strcmp(object_dir, m_search->object_dir)) return 1; - m = load_multi_pack_index(object_dir, local); + m = load_multi_pack_index(r, object_dir, local); if (m) { struct multi_pack_index *mp = r->objects->multi_pack_index; @@ -494,7 +749,8 @@ int midx_checksum_valid(struct multi_pack_index *m) } struct clear_midx_data { - char *keep; + char **keep; + uint32_t keep_nr; const char *ext; }; @@ -502,32 +758,63 @@ static void clear_midx_file_ext(const char *full_path, size_t full_path_len UNUS const char *file_name, void *_data) { struct clear_midx_data *data = _data; + uint32_t i; if (!(starts_with(file_name, "multi-pack-index-") && ends_with(file_name, data->ext))) return; - if (data->keep && !strcmp(data->keep, file_name)) - return; - + for (i = 0; i < data->keep_nr; i++) { + if (!strcmp(data->keep[i], file_name)) + return; + } if (unlink(full_path)) die_errno(_("failed to remove %s"), full_path); } void clear_midx_files_ext(const char *object_dir, const char *ext, - unsigned char *keep_hash) + const char *keep_hash) { struct clear_midx_data data; memset(&data, 0, sizeof(struct clear_midx_data)); - if (keep_hash) - data.keep = xstrfmt("multi-pack-index-%s%s", - hash_to_hex(keep_hash), ext); + if (keep_hash) { + ALLOC_ARRAY(data.keep, 1); + + data.keep[0] = xstrfmt("multi-pack-index-%s.%s", keep_hash, ext); + data.keep_nr = 1; + } data.ext = ext; for_each_file_in_pack_dir(object_dir, clear_midx_file_ext, &data); + if (keep_hash) + free(data.keep[0]); + free(data.keep); +} + +void clear_incremental_midx_files_ext(const char *object_dir, const char *ext, + char **keep_hashes, + uint32_t hashes_nr) +{ + struct clear_midx_data data; + uint32_t i; + + memset(&data, 0, sizeof(struct clear_midx_data)); + + ALLOC_ARRAY(data.keep, hashes_nr); + for (i = 0; i < hashes_nr; i++) + data.keep[i] = xstrfmt("multi-pack-index-%s.%s", keep_hashes[i], + ext); + data.keep_nr = hashes_nr; + data.ext = ext; + + for_each_file_in_pack_subdir(object_dir, "multi-pack-index.d", + clear_midx_file_ext, &data); + + for (i = 0; i < hashes_nr; i++) + free(data.keep[i]); free(data.keep); } @@ -535,7 +822,7 @@ void clear_midx_file(struct repository *r) { struct strbuf midx = STRBUF_INIT; - get_midx_filename(&midx, r->objects->odb->path); + get_midx_filename(r->hash_algo, &midx, r->objects->odb->path); if (r->objects && r->objects->multi_pack_index) { close_midx(r->objects->multi_pack_index); @@ -545,8 +832,8 @@ void clear_midx_file(struct repository *r) if (remove_path(midx.buf)) die(_("failed to clear multi-pack-index at %s"), midx.buf); - clear_midx_files_ext(r->objects->odb->path, ".bitmap", NULL); - clear_midx_files_ext(r->objects->odb->path, ".rev", NULL); + clear_midx_files_ext(r->objects->odb->path, MIDX_EXT_BITMAP, NULL); + clear_midx_files_ext(r->objects->odb->path, MIDX_EXT_REV, NULL); strbuf_release(&midx); } @@ -595,7 +882,8 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag struct pair_pos_vs_id *pairs = NULL; uint32_t i; struct progress *progress = NULL; - struct multi_pack_index *m = load_multi_pack_index(object_dir, 1); + struct multi_pack_index *m = load_multi_pack_index(r, object_dir, 1); + struct multi_pack_index *curr; verify_midx_error = 0; if (!m) { @@ -603,7 +891,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag struct stat sb; struct strbuf filename = STRBUF_INIT; - get_midx_filename(&filename, object_dir); + get_midx_filename(r->hash_algo, &filename, object_dir); if (!stat(filename.buf, &sb)) { error(_("multi-pack-index file exists, but failed to parse")); @@ -618,8 +906,8 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag if (flags & MIDX_PROGRESS) progress = start_delayed_progress(_("Looking for referenced packfiles"), - m->num_packs); - for (i = 0; i < m->num_packs; i++) { + m->num_packs + m->num_packs_in_base); + for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) { if (prepare_midx_pack(r, m, i)) midx_report("failed to load pack in position %d", i); @@ -639,17 +927,20 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag if (flags & MIDX_PROGRESS) progress = start_sparse_progress(_("Verifying OID order in multi-pack-index"), m->num_objects - 1); - for (i = 0; i < m->num_objects - 1; i++) { - struct object_id oid1, oid2; - nth_midxed_object_oid(&oid1, m, i); - nth_midxed_object_oid(&oid2, m, i + 1); + for (curr = m; curr; curr = curr->base_midx) { + for (i = 0; i < m->num_objects - 1; i++) { + struct object_id oid1, oid2; - if (oidcmp(&oid1, &oid2) >= 0) - midx_report(_("oid lookup out of order: oid[%d] = %s >= %s = oid[%d]"), - i, oid_to_hex(&oid1), oid_to_hex(&oid2), i + 1); + nth_midxed_object_oid(&oid1, m, m->num_objects_in_base + i); + nth_midxed_object_oid(&oid2, m, m->num_objects_in_base + i + 1); - midx_display_sparse_progress(progress, i + 1); + if (oidcmp(&oid1, &oid2) >= 0) + midx_report(_("oid lookup out of order: oid[%d] = %s >= %s = oid[%d]"), + i, oid_to_hex(&oid1), oid_to_hex(&oid2), i + 1); + + midx_display_sparse_progress(progress, i + 1); + } } stop_progress(&progress); @@ -659,8 +950,8 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag * each of the objects and only require 1 packfile to be open at a * time. */ - ALLOC_ARRAY(pairs, m->num_objects); - for (i = 0; i < m->num_objects; i++) { + ALLOC_ARRAY(pairs, m->num_objects + m->num_objects_in_base); + for (i = 0; i < m->num_objects + m->num_objects_in_base; i++) { pairs[i].pos = i; pairs[i].pack_int_id = nth_midxed_pack_int_id(m, i); } @@ -674,16 +965,18 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag if (flags & MIDX_PROGRESS) progress = start_sparse_progress(_("Verifying object offsets"), m->num_objects); - for (i = 0; i < m->num_objects; i++) { + for (i = 0; i < m->num_objects + m->num_objects_in_base; i++) { struct object_id oid; struct pack_entry e; off_t m_offset, p_offset; if (i > 0 && pairs[i-1].pack_int_id != pairs[i].pack_int_id && - m->packs[pairs[i-1].pack_int_id]) - { - close_pack_fd(m->packs[pairs[i-1].pack_int_id]); - close_pack_index(m->packs[pairs[i-1].pack_int_id]); + nth_midxed_pack(m, pairs[i-1].pack_int_id)) { + uint32_t pack_int_id = pairs[i-1].pack_int_id; + struct packed_git *p = nth_midxed_pack(m, pack_int_id); + + close_pack_fd(p); + close_pack_index(p); } nth_midxed_object_oid(&oid, m, pairs[i].pos); @@ -701,7 +994,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag } m_offset = e.offset; - p_offset = find_pack_entry_one(oid.hash, e.p); + p_offset = find_pack_entry_one(&oid, e.p); if (m_offset != p_offset) midx_report(_("incorrect object offset for oid[%d] = %s: %"PRIx64" != %"PRIx64), @@ -7,6 +7,7 @@ struct object_id; struct pack_entry; struct repository; struct bitmapped_pack; +struct git_hash_algo; #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ #define MIDX_VERSION 1 @@ -24,12 +25,13 @@ struct bitmapped_pack; #define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */ #define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */ #define MIDX_CHUNKID_REVINDEX 0x52494458 /* "RIDX" */ +#define MIDX_CHUNKID_BASE 0x42415345 /* "BASE" */ #define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t)) #define MIDX_LARGE_OFFSET_NEEDED 0x80000000 #define GIT_TEST_MULTI_PACK_INDEX "GIT_TEST_MULTI_PACK_INDEX" -#define GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP \ - "GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP" +#define GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL \ + "GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL" struct multi_pack_index { struct multi_pack_index *next; @@ -50,6 +52,7 @@ struct multi_pack_index { int preferred_pack_idx; int local; + int has_chain; const unsigned char *chunk_pack_names; size_t chunk_pack_names_len; @@ -63,8 +66,15 @@ struct multi_pack_index { const unsigned char *chunk_revindex; size_t chunk_revindex_len; + struct multi_pack_index *base_midx; + uint32_t num_objects_in_base; + uint32_t num_packs_in_base; + const char **pack_names; struct packed_git **packs; + + struct repository *repo; + char object_dir[FLEX_ARRAY]; }; @@ -73,20 +83,37 @@ struct multi_pack_index { #define MIDX_WRITE_BITMAP (1 << 2) #define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3) #define MIDX_WRITE_BITMAP_LOOKUP_TABLE (1 << 4) +#define MIDX_WRITE_INCREMENTAL (1 << 5) #define MIDX_EXT_REV "rev" #define MIDX_EXT_BITMAP "bitmap" +#define MIDX_EXT_MIDX "midx" const unsigned char *get_midx_checksum(struct multi_pack_index *m); -void get_midx_filename(struct strbuf *out, const char *object_dir); -void get_midx_filename_ext(struct strbuf *out, const char *object_dir, +void get_midx_filename(const struct git_hash_algo *hash_algo, + struct strbuf *out, const char *object_dir); +void get_midx_filename_ext(const struct git_hash_algo *hash_algo, + struct strbuf *out, const char *object_dir, const unsigned char *hash, const char *ext); - -struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local); +void get_midx_chain_dirname(struct strbuf *buf, const char *object_dir); +void get_midx_chain_filename(struct strbuf *buf, const char *object_dir); +void get_split_midx_filename_ext(const struct git_hash_algo *hash_algo, + struct strbuf *buf, const char *object_dir, + const unsigned char *hash, const char *ext); + +struct multi_pack_index *load_multi_pack_index(struct repository *r, + const char *object_dir, + int local); int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id); +struct packed_git *nth_midxed_pack(struct multi_pack_index *m, + uint32_t pack_int_id); int nth_bitmapped_pack(struct repository *r, struct multi_pack_index *m, struct bitmapped_pack *bp, uint32_t pack_int_id); -int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result); +int bsearch_one_midx(const struct object_id *oid, struct multi_pack_index *m, + uint32_t *result); +int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, + uint32_t *result); +int midx_has_oid(struct multi_pack_index *m, const struct object_id *oid); off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos); uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos); struct object_id *nth_midxed_object_oid(struct object_id *oid, @@ -95,8 +122,6 @@ struct object_id *nth_midxed_object_oid(struct object_id *oid, int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m); int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name); -int midx_locate_pack(struct multi_pack_index *m, const char *idx_or_pack_name, - uint32_t *pos); int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id); int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local); @@ -104,15 +129,13 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i * Variant of write_midx_file which writes a MIDX containing only the packs * specified in packs_to_include. */ -int write_midx_file(const char *object_dir, - const char *preferred_pack_name, - const char *refs_snapshot, +int write_midx_file(struct repository *r, const char *object_dir, + const char *preferred_pack_name, const char *refs_snapshot, unsigned flags); -int write_midx_file_only(const char *object_dir, +int write_midx_file_only(struct repository *r, const char *object_dir, struct string_list *packs_to_include, const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags); + const char *refs_snapshot, unsigned flags); void clear_midx_file(struct repository *r); int verify_midx_file(struct repository *r, const char *object_dir, unsigned flags); int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags); diff --git a/name-hash.c b/name-hash.c index 3a58ce03d9..95528e3bcd 100644 --- a/name-hash.c +++ b/name-hash.c @@ -5,6 +5,9 @@ * * Copyright (C) 2008 Linus Torvalds */ + +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "environment.h" #include "gettext.h" diff --git a/negotiator/default.c b/negotiator/default.c index e3fa5c3324..c479da9b09 100644 --- a/negotiator/default.c +++ b/negotiator/default.c @@ -38,7 +38,7 @@ static void rev_list_push(struct negotiation_state *ns, } } -static int clear_marks(const char *refname, const struct object_id *oid, +static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { diff --git a/negotiator/skipping.c b/negotiator/skipping.c index f109928ad0..abedb70a48 100644 --- a/negotiator/skipping.c +++ b/negotiator/skipping.c @@ -75,7 +75,7 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int return entry; } -static int clear_marks(const char *refname, const struct object_id *oid, +static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { @@ -239,7 +239,7 @@ static int ack(struct fetch_negotiator *n, struct commit *c) { int known_to_be_common = !!(c->object.flags & COMMON); if (!(c->object.flags & SEEN)) - die("received ack for commit %s not sent as 'have'\n", + die("received ack for commit %s not sent as 'have'", oid_to_hex(&c->object.oid)); mark_common(n->data, c); return known_to_be_common; @@ -247,8 +247,11 @@ static int ack(struct fetch_negotiator *n, struct commit *c) static void release(struct fetch_negotiator *n) { - clear_prio_queue(&((struct data *)n->data)->rev_list); - FREE_AND_NULL(n->data); + struct data *data = n->data; + for (int i = 0; i < data->rev_list.nr; i++) + free(data->rev_list.array[i].data); + clear_prio_queue(&data->rev_list); + FREE_AND_NULL(data); } void skipping_negotiator_init(struct fetch_negotiator *negotiator) @@ -932,7 +932,7 @@ out: return ret; } -static int string_list_add_one_ref(const char *refname, +static int string_list_add_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cb) { @@ -992,15 +992,16 @@ static int notes_display_config(const char *k, const char *v, return 0; } -const char *default_notes_ref(void) +char *default_notes_ref(struct repository *repo) { - const char *notes_ref = NULL; + char *notes_ref = NULL; + if (!notes_ref) - notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT); + notes_ref = xstrdup_or_null(getenv(GIT_NOTES_REF_ENVIRONMENT)); if (!notes_ref) - notes_ref = notes_ref_name; /* value of core.notesRef config */ + repo_config_get_string(repo, "core.notesref", ¬es_ref); if (!notes_ref) - notes_ref = GIT_NOTES_DEFAULT_REF; + notes_ref = xstrdup(GIT_NOTES_DEFAULT_REF); return notes_ref; } @@ -1010,13 +1011,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref, struct object_id oid, object_oid; unsigned short mode; struct leaf_node root_tree; + char *to_free = NULL; if (!t) t = &default_notes_tree; assert(!t->initialized); if (!notes_ref) - notes_ref = default_notes_ref(); + notes_ref = to_free = default_notes_ref(the_repository); update_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref)); if (!combine_notes) @@ -1033,7 +1035,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref, if (flags & NOTES_INIT_EMPTY || repo_get_oid_treeish(the_repository, notes_ref, &object_oid)) - return; + goto out; if (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid)) die("Cannot use notes ref %s", notes_ref); if (get_tree_entry(the_repository, &object_oid, "", &oid, &mode)) @@ -1043,6 +1045,9 @@ void init_notes(struct notes_tree *t, const char *notes_ref, oidclr(&root_tree.key_oid, the_repository->hash_algo); oidcpy(&root_tree.val_oid, &oid); load_subtree(t, &root_tree, t->root, 0); + +out: + free(to_free); } struct notes_tree **load_notes_trees(struct string_list *refs, int flags) @@ -1105,7 +1110,7 @@ void load_display_notes(struct display_notes_opt *opt) if (!opt || opt->use_default_notes > 0 || (opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) { - string_list_append(&display_notes_refs, default_notes_ref()); + string_list_append_nodup(&display_notes_refs, default_notes_ref(the_repository)); display_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT); if (display_ref_env) { string_list_add_refs_from_colon_sep(&display_notes_refs, @@ -4,6 +4,7 @@ #include "string-list.h" struct object_id; +struct repository; struct strbuf; /* @@ -70,7 +71,7 @@ extern struct notes_tree { * 3. The value of the core.notesRef config variable, if set * 4. GIT_NOTES_DEFAULT_REF (i.e. "refs/notes/commits") */ -const char *default_notes_ref(void); +char *default_notes_ref(struct repository *repo); /* * Flags controlling behaviour of notes tree initialization diff --git a/object-file.c b/object-file.c index 065103be3e..891eaa2b4b 100644 --- a/object-file.c +++ b/object-file.c @@ -44,31 +44,18 @@ /* The maximum size for an object header. */ #define MAX_HEADER_LEN 32 - -#define EMPTY_TREE_SHA1_BIN_LITERAL \ - "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \ - "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04" -#define EMPTY_TREE_SHA256_BIN_LITERAL \ - "\x6e\xf1\x9b\x41\x22\x5c\x53\x69\xf1\xc1" \ - "\x04\xd4\x5d\x8d\x85\xef\xa9\xb0\x57\xb5" \ - "\x3b\x14\xb4\xb9\xb9\x39\xdd\x74\xde\xcc" \ - "\x53\x21" - -#define EMPTY_BLOB_SHA1_BIN_LITERAL \ - "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \ - "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91" -#define EMPTY_BLOB_SHA256_BIN_LITERAL \ - "\x47\x3a\x0f\x4c\x3b\xe8\xa9\x36\x81\xa2" \ - "\x67\xe3\xb1\xe9\xa7\xdc\xda\x11\x85\x43" \ - "\x6f\xe1\x41\xf7\x74\x91\x20\xa3\x03\x72" \ - "\x18\x13" - static const struct object_id empty_tree_oid = { - .hash = EMPTY_TREE_SHA1_BIN_LITERAL, + .hash = { + 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, + 0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 + }, .algo = GIT_HASH_SHA1, }; static const struct object_id empty_blob_oid = { - .hash = EMPTY_BLOB_SHA1_BIN_LITERAL, + .hash = { + 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b, + 0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 + }, .algo = GIT_HASH_SHA1, }; static const struct object_id null_oid_sha1 = { @@ -76,11 +63,21 @@ static const struct object_id null_oid_sha1 = { .algo = GIT_HASH_SHA1, }; static const struct object_id empty_tree_oid_sha256 = { - .hash = EMPTY_TREE_SHA256_BIN_LITERAL, + .hash = { + 0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1, + 0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5, + 0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc, + 0x53, 0x21 + }, .algo = GIT_HASH_SHA256, }; static const struct object_id empty_blob_oid_sha256 = { - .hash = EMPTY_BLOB_SHA256_BIN_LITERAL, + .hash = { + 0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2, + 0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43, + 0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72, + 0x18, 0x13 + }, .algo = GIT_HASH_SHA256, }; static const struct object_id null_oid_sha256 = { @@ -115,6 +112,33 @@ static void git_hash_sha1_final_oid(struct object_id *oid, git_hash_ctx *ctx) oid->algo = GIT_HASH_SHA1; } +static void git_hash_sha1_init_unsafe(git_hash_ctx *ctx) +{ + git_SHA1_Init_unsafe(&ctx->sha1_unsafe); +} + +static void git_hash_sha1_clone_unsafe(git_hash_ctx *dst, const git_hash_ctx *src) +{ + git_SHA1_Clone_unsafe(&dst->sha1_unsafe, &src->sha1_unsafe); +} + +static void git_hash_sha1_update_unsafe(git_hash_ctx *ctx, const void *data, + size_t len) +{ + git_SHA1_Update_unsafe(&ctx->sha1_unsafe, data, len); +} + +static void git_hash_sha1_final_unsafe(unsigned char *hash, git_hash_ctx *ctx) +{ + git_SHA1_Final_unsafe(hash, &ctx->sha1_unsafe); +} + +static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, git_hash_ctx *ctx) +{ + git_SHA1_Final_unsafe(oid->hash, &ctx->sha1_unsafe); + memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); + oid->algo = GIT_HASH_SHA1; +} static void git_hash_sha256_init(git_hash_ctx *ctx) { @@ -189,6 +213,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_unknown_update, .final_fn = git_hash_unknown_final, .final_oid_fn = git_hash_unknown_final_oid, + .unsafe_init_fn = git_hash_unknown_init, + .unsafe_clone_fn = git_hash_unknown_clone, + .unsafe_update_fn = git_hash_unknown_update, + .unsafe_final_fn = git_hash_unknown_final, + .unsafe_final_oid_fn = git_hash_unknown_final_oid, .empty_tree = NULL, .empty_blob = NULL, .null_oid = NULL, @@ -204,6 +233,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_sha1_update, .final_fn = git_hash_sha1_final, .final_oid_fn = git_hash_sha1_final_oid, + .unsafe_init_fn = git_hash_sha1_init_unsafe, + .unsafe_clone_fn = git_hash_sha1_clone_unsafe, + .unsafe_update_fn = git_hash_sha1_update_unsafe, + .unsafe_final_fn = git_hash_sha1_final_unsafe, + .unsafe_final_oid_fn = git_hash_sha1_final_oid_unsafe, .empty_tree = &empty_tree_oid, .empty_blob = &empty_blob_oid, .null_oid = &null_oid_sha1, @@ -219,6 +253,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { .update_fn = git_hash_sha256_update, .final_fn = git_hash_sha256_final, .final_oid_fn = git_hash_sha256_final_oid, + .unsafe_init_fn = git_hash_sha256_init, + .unsafe_clone_fn = git_hash_sha256_clone, + .unsafe_update_fn = git_hash_sha256_update, + .unsafe_final_fn = git_hash_sha256_final, + .unsafe_final_oid_fn = git_hash_sha256_final_oid, .empty_tree = &empty_tree_oid_sha256, .empty_blob = &empty_blob_oid_sha256, .null_oid = &null_oid_sha256, @@ -271,30 +310,28 @@ int hash_algo_by_length(int len) * to write them into the object store (e.g. a browse-only * application). */ -static struct cached_object { +static struct cached_object_entry { struct object_id oid; - enum object_type type; - const void *buf; - unsigned long size; + struct cached_object { + enum object_type type; + const void *buf; + unsigned long size; + } value; } *cached_objects; static int cached_object_nr, cached_object_alloc; -static struct cached_object empty_tree = { - .oid = { - .hash = EMPTY_TREE_SHA1_BIN_LITERAL, - }, - .type = OBJ_TREE, - .buf = "", -}; - -static struct cached_object *find_cached_object(const struct object_id *oid) +static const struct cached_object *find_cached_object(const struct object_id *oid) { + static const struct cached_object empty_tree = { + .type = OBJ_TREE, + .buf = "", + }; int i; - struct cached_object *co = cached_objects; + const struct cached_object_entry *co = cached_objects; for (i = 0; i < cached_object_nr; i++, co++) { if (oideq(&co->oid, oid)) - return co; + return &co->value; } if (oideq(oid, the_hash_algo->empty_tree)) return &empty_tree; @@ -419,6 +456,39 @@ enum scld_error safe_create_leading_directories_const(const char *path) return result; } +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) +{ + int fd; + /* + * we let the umask do its job, don't try to be more + * restrictive except to remove write permission. + */ + int mode = 0444; + git_path_buf(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); + safe_create_leading_directories(temp_filename->buf); + return xmkstemp_mode(temp_filename->buf, mode); +} + +int odb_pack_keep(const char *name) +{ + int fd; + + fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600); + if (0 <= fd) + return fd; + + /* slow path */ + safe_create_leading_directories_const(name); + return open(name, O_RDWR|O_CREAT|O_EXCL, 0600); +} + static void fill_loose_path(struct strbuf *buf, const struct object_id *oid) { int i; @@ -1552,7 +1622,7 @@ static int do_oid_object_info_extended(struct repository *r, struct object_info *oi, unsigned flags) { static struct object_info blank_oi = OBJECT_INFO_INIT; - struct cached_object *co; + const struct cached_object *co; struct pack_entry e; int rtype; const struct object_id *real = oid; @@ -1774,7 +1844,7 @@ int oid_object_info(struct repository *r, int pretend_object_file(void *buf, unsigned long len, enum object_type type, struct object_id *oid) { - struct cached_object *co; + struct cached_object_entry *co; char *co_buf; hash_object_file(the_hash_algo, buf, len, type, oid); @@ -1783,11 +1853,11 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, return 0; ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc); co = &cached_objects[cached_object_nr++]; - co->size = len; - co->type = type; + co->value.size = len; + co->value.type = type; co_buf = xmalloc(len); memcpy(co_buf, buf, len); - co->buf = co_buf; + co->value.buf = co_buf; oidcpy(&co->oid, oid); return 0; } @@ -1899,17 +1969,77 @@ static void write_object_file_prepare_literally(const struct git_hash_algo *algo hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } +static int check_collision(const char *filename_a, const char *filename_b) +{ + char buf_a[4096], buf_b[4096]; + int fd_a = -1, fd_b = -1; + int ret = 0; + + fd_a = open(filename_a, O_RDONLY); + if (fd_a < 0) { + ret = error_errno(_("unable to open %s"), filename_a); + goto out; + } + + fd_b = open(filename_b, O_RDONLY); + if (fd_b < 0) { + ret = error_errno(_("unable to open %s"), filename_b); + goto out; + } + + while (1) { + ssize_t sz_a, sz_b; + + sz_a = read_in_full(fd_a, buf_a, sizeof(buf_a)); + if (sz_a < 0) { + ret = error_errno(_("unable to read %s"), filename_a); + goto out; + } + + sz_b = read_in_full(fd_b, buf_b, sizeof(buf_b)); + if (sz_b < 0) { + ret = error_errno(_("unable to read %s"), filename_b); + goto out; + } + + if (sz_a != sz_b || memcmp(buf_a, buf_b, sz_a)) { + ret = error(_("files '%s' and '%s' differ in contents"), + filename_a, filename_b); + goto out; + } + + if (sz_a < sizeof(buf_a)) + break; + } + +out: + if (fd_a > -1) + close(fd_a); + if (fd_b > -1) + close(fd_b); + return ret; +} + /* * Move the just written object into its final resting place. */ int finalize_object_file(const char *tmpfile, const char *filename) { + return finalize_object_file_flags(tmpfile, filename, 0); +} + +int finalize_object_file_flags(const char *tmpfile, const char *filename, + enum finalize_object_file_flags flags) +{ + struct stat st; int ret = 0; if (object_creation_mode == OBJECT_CREATION_USES_RENAMES) goto try_rename; else if (link(tmpfile, filename)) ret = errno; + else + unlink_or_warn(tmpfile); /* * Coda hack - coda doesn't like cross-directory links, @@ -1924,16 +2054,24 @@ int finalize_object_file(const char *tmpfile, const char *filename) */ if (ret && ret != EEXIST) { try_rename: - if (!rename(tmpfile, filename)) + if (!stat(filename, &st)) + ret = EEXIST; + else if (!rename(tmpfile, filename)) goto out; - ret = errno; + else + ret = errno; } - unlink_or_warn(tmpfile); if (ret) { if (ret != EEXIST) { + int saved_errno = errno; + unlink_or_warn(tmpfile); + errno = saved_errno; return error_errno(_("unable to write file %s"), filename); } - /* FIXME!!! Collision check here ? */ + if (!(flags & FOF_SKIP_COLLISION_CHECK) && + check_collision(tmpfile, filename)) + return -1; + unlink_or_warn(tmpfile); } out: @@ -2053,7 +2191,7 @@ static int start_loose_object_common(struct strbuf *tmp_file, else if (errno == EACCES) return error(_("insufficient permission for adding " "an object to repository database %s"), - get_object_directory()); + repo_get_object_directory(the_repository)); else return error_errno( _("unable to create temporary file")); @@ -2186,7 +2324,8 @@ static int write_loose_object(const struct object_id *oid, char *hdr, warning_errno(_("failed utime() on %s"), tmp_file.buf); } - return finalize_object_file(tmp_file.buf, filename.buf); + return finalize_object_file_flags(tmp_file.buf, filename.buf, + FOF_SKIP_COLLISION_CHECK); } static int freshen_loose_object(const struct object_id *oid) @@ -2228,7 +2367,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, prepare_loose_object_bulk_checkin(); /* Since oid is not determined, save tmp file to odb path. */ - strbuf_addf(&filename, "%s/", get_object_directory()); + strbuf_addf(&filename, "%s/", repo_get_object_directory(the_repository)); hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len); /* @@ -2275,7 +2414,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, /* * Common steps for write_loose_object and stream_loose_object to - * end writing loose oject: + * end writing loose object: * * - End the compression of zlib stream. * - Get the calculated oid. @@ -2308,7 +2447,8 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, strbuf_release(&dir); } - err = finalize_object_file(tmp_file.buf, filename.buf); + err = finalize_object_file_flags(tmp_file.buf, filename.buf, + FOF_SKIP_COLLISION_CHECK); if (!err && compat) err = repo_add_loose_object_map(the_repository, oid, &compat_oid); cleanup: @@ -2470,11 +2610,10 @@ int repo_has_object_file(struct repository *r, * give more context. */ static int hash_format_check_report(struct fsck_options *opts UNUSED, - const struct object_id *oid UNUSED, - enum object_type object_type UNUSED, - enum fsck_msg_type msg_type UNUSED, - enum fsck_msg_id msg_id UNUSED, - const char *message) + void *fsck_report UNUSED, + enum fsck_msg_type msg_type UNUSED, + enum fsck_msg_id msg_id UNUSED, + const char *message) { error(_("object fails fsck: %s"), message); return 1; @@ -2954,6 +3093,7 @@ int read_loose_object(const char *path, if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr), NULL) != ULHR_OK) { error(_("unable to unpack header of %s"), path); + git_inflate_end(&stream); goto out; } diff --git a/object-file.h b/object-file.h index d6414610f8..81b30d269c 100644 --- a/object-file.h +++ b/object-file.h @@ -117,7 +117,13 @@ int check_object_signature(struct repository *r, const struct object_id *oid, */ int stream_object_signature(struct repository *r, const struct object_id *oid); +enum finalize_object_file_flags { + FOF_SKIP_COLLISION_CHECK = 1, +}; + int finalize_object_file(const char *tmpfile, const char *filename); +int finalize_object_file_flags(const char *tmpfile, const char *filename, + enum finalize_object_file_flags flags); /* Helper to check and "touch" a file */ int check_and_freshen_file(const char *fn, int freshen); diff --git a/object-name.c b/object-name.c index 4c50559ee8..a563635a8c 100644 --- a/object-name.c +++ b/object-name.c @@ -20,6 +20,7 @@ #include "pretty.h" #include "object-store-ll.h" #include "read-cache-ll.h" +#include "repo-settings.h" #include "repository.h" #include "setup.h" #include "midx.h" @@ -135,28 +136,32 @@ static int match_hash(unsigned len, const unsigned char *a, const unsigned char static void unique_in_midx(struct multi_pack_index *m, struct disambiguate_state *ds) { - uint32_t num, i, first = 0; - const struct object_id *current = NULL; - int len = ds->len > ds->repo->hash_algo->hexsz ? - ds->repo->hash_algo->hexsz : ds->len; - num = m->num_objects; + for (; m; m = m->base_midx) { + uint32_t num, i, first = 0; + const struct object_id *current = NULL; + int len = ds->len > ds->repo->hash_algo->hexsz ? + ds->repo->hash_algo->hexsz : ds->len; - if (!num) - return; + if (!m->num_objects) + continue; - bsearch_midx(&ds->bin_pfx, m, &first); + num = m->num_objects + m->num_objects_in_base; - /* - * At this point, "first" is the location of the lowest object - * with an object name that could match "bin_pfx". See if we have - * 0, 1 or more objects that actually match(es). - */ - for (i = first; i < num && !ds->ambiguous; i++) { - struct object_id oid; - current = nth_midxed_object_oid(&oid, m, i); - if (!match_hash(len, ds->bin_pfx.hash, current->hash)) - break; - update_candidates(ds, current); + bsearch_one_midx(&ds->bin_pfx, m, &first); + + /* + * At this point, "first" is the location of the lowest + * object with an object name that could match + * "bin_pfx". See if we have 0, 1 or more objects that + * actually match(es). + */ + for (i = first; i < num && !ds->ambiguous; i++) { + struct object_id oid; + current = nth_midxed_object_oid(&oid, m, i); + if (!match_hash(len, ds->bin_pfx.hash, current->hash)) + break; + update_candidates(ds, current); + } } } @@ -709,37 +714,40 @@ static int repo_extend_abbrev_len(struct repository *r UNUSED, static void find_abbrev_len_for_midx(struct multi_pack_index *m, struct min_abbrev_data *mad) { - int match = 0; - uint32_t num, first = 0; - struct object_id oid; - const struct object_id *mad_oid; + for (; m; m = m->base_midx) { + int match = 0; + uint32_t num, first = 0; + struct object_id oid; + const struct object_id *mad_oid; - if (!m->num_objects) - return; + if (!m->num_objects) + continue; - num = m->num_objects; - mad_oid = mad->oid; - match = bsearch_midx(mad_oid, m, &first); + num = m->num_objects + m->num_objects_in_base; + mad_oid = mad->oid; + match = bsearch_one_midx(mad_oid, m, &first); - /* - * first is now the position in the packfile where we would insert - * mad->hash if it does not exist (or the position of mad->hash if - * it does exist). Hence, we consider a maximum of two objects - * nearby for the abbreviation length. - */ - mad->init_len = 0; - if (!match) { - if (nth_midxed_object_oid(&oid, m, first)) - extend_abbrev_len(&oid, mad); - } else if (first < num - 1) { - if (nth_midxed_object_oid(&oid, m, first + 1)) - extend_abbrev_len(&oid, mad); - } - if (first > 0) { - if (nth_midxed_object_oid(&oid, m, first - 1)) - extend_abbrev_len(&oid, mad); + /* + * first is now the position in the packfile where we + * would insert mad->hash if it does not exist (or the + * position of mad->hash if it does exist). Hence, we + * consider a maximum of two objects nearby for the + * abbreviation length. + */ + mad->init_len = 0; + if (!match) { + if (nth_midxed_object_oid(&oid, m, first)) + extend_abbrev_len(&oid, mad); + } else if (first < num - 1) { + if (nth_midxed_object_oid(&oid, m, first + 1)) + extend_abbrev_len(&oid, mad); + } + if (first > 0) { + if (nth_midxed_object_oid(&oid, m, first - 1)) + extend_abbrev_len(&oid, mad); + } + mad->init_len = mad->cur_len; } - mad->init_len = mad->cur_len; } static void find_abbrev_len_for_pack(struct packed_git *p, @@ -944,7 +952,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len, "\n" "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n" "examine these refs and maybe delete them. Turn this message off by\n" - "running \"git config advice.objectNameWarning false\""); + "running \"git config set advice.objectNameWarning false\""); struct object_id tmp_oid; char *real_ref = NULL; int refs_found = 0; @@ -952,7 +960,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len, int fatal = !(flags & GET_OID_QUIETLY); if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) { - if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) { + if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) { refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0); if (refs_found > 0) { warning(warn_msg, len, str); @@ -1013,7 +1021,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len, if (!refs_found) return -1; - if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) && + if (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) && (refs_found > 1 || !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY))) warning(warn_msg, len, str); @@ -1368,7 +1376,7 @@ struct handle_one_ref_cb { struct commit_list **list; }; -static int handle_one_ref(const char *path, const struct object_id *oid, +static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -1726,45 +1734,10 @@ int repo_interpret_branch_name(struct repository *r, return -1; } -void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed) -{ - int len = strlen(name); - struct interpret_branch_name_options options = { - .allowed = allowed - }; - int used = repo_interpret_branch_name(the_repository, name, len, sb, - &options); - - if (used < 0) - used = 0; - strbuf_add(sb, name + used, len - used); -} - -int strbuf_check_branch_ref(struct strbuf *sb, const char *name) -{ - if (startup_info->have_repository) - strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL); - else - strbuf_addstr(sb, name); - - /* - * This splice must be done even if we end up rejecting the - * name; builtin/branch.c::copy_or_rename_branch() still wants - * to see what the name expanded to so that "branch -m" can be - * used as a tool to correct earlier mistakes. - */ - strbuf_splice(sb, 0, 0, "refs/heads/", 11); - - if (*name == '-' || - !strcmp(sb->buf, "refs/heads/HEAD")) - return -1; - - return check_refname_format(sb->buf, 0); -} - void object_context_release(struct object_context *ctx) { free(ctx->path); + strbuf_release(&ctx->symlink_path); } /* diff --git a/object-store-ll.h b/object-store-ll.h index c5f2bb2fc2..cd3bd5bd99 100644 --- a/object-store-ll.h +++ b/object-store-ll.h @@ -10,6 +10,7 @@ struct oidmap; struct oidtree; struct strbuf; +struct repository; struct object_directory { struct object_directory *next; @@ -135,6 +136,10 @@ struct packed_git { */ const uint32_t *mtimes_map; size_t mtimes_size; + + /* repo denotes the repository this packfile belongs to */ + struct repository *repo; + /* something like ".git/objects/pack/xxxxx.pack" */ char pack_name[FLEX_ARRAY]; /* more */ }; @@ -232,6 +237,21 @@ struct raw_object_store *raw_object_store_new(void); void raw_object_store_clear(struct raw_object_store *o); /* + * Create a temporary file rooted in the object database directory, or + * die on failure. The filename is taken from "pattern", which should have the + * usual "XXXXXX" trailer, and the resulting filename is written into the + * "template" buffer. Returns the open descriptor. + */ +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); + +/* + * Create a pack .keep file named "name" (which should generally be the output + * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on + * error. + */ +int odb_pack_keep(const char *name); + +/* * Put in `buf` the name of the file in the local object database that * would be used to store a loose object with the specified oid. */ @@ -530,7 +550,7 @@ typedef int each_packed_object_fn(const struct object_id *oid, int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn, void *data, enum for_each_object_flags flags); -int for_each_packed_object(each_packed_object_fn, void *, - enum for_each_object_flags flags); +int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, + void *data, enum for_each_object_flags flags); #endif /* OBJECT_STORE_LL_H */ @@ -545,11 +545,12 @@ void repo_clear_commit_marks(struct repository *r, unsigned int flags) } } -struct parsed_object_pool *parsed_object_pool_new(void) +struct parsed_object_pool *parsed_object_pool_new(struct repository *repo) { struct parsed_object_pool *o = xmalloc(sizeof(*o)); memset(o, 0, sizeof(*o)); + o->repo = repo; o->blob_state = allocate_alloc_state(); o->tree_state = allocate_alloc_state(); o->commit_state = allocate_alloc_state(); @@ -614,11 +615,30 @@ void raw_object_store_clear(struct raw_object_store *o) INIT_LIST_HEAD(&o->packed_git_mru); close_object_store(o); + + /* + * `close_object_store()` only closes the packfiles, but doesn't free + * them. We thus have to do this manually. + */ + for (struct packed_git *p = o->packed_git, *next; p; p = next) { + next = p->next; + free(p); + } o->packed_git = NULL; hashmap_clear(&o->pack_map); } +void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o) +{ + for (int i = 0; i < o->grafts_nr; i++) { + unparse_commit(o->repo, &o->grafts[i]->oid); + free(o->grafts[i]); + } + o->grafts_nr = 0; + o->commit_graft_prepared = 0; +} + void parsed_object_pool_clear(struct parsed_object_pool *o) { /* @@ -650,6 +670,7 @@ void parsed_object_pool_clear(struct parsed_object_pool *o) free_commit_buffer_slab(o->buffer_slab); o->buffer_slab = NULL; + parsed_object_pool_reset_commit_grafts(o); clear_alloc_state(o->blob_state); clear_alloc_state(o->tree_state); clear_alloc_state(o->commit_state); @@ -7,6 +7,7 @@ struct buffer_slab; struct repository; struct parsed_object_pool { + struct repository *repo; struct object **obj_hash; int nr_objs, obj_hash_size; @@ -31,8 +32,9 @@ struct parsed_object_pool { struct buffer_slab *buffer_slab; }; -struct parsed_object_pool *parsed_object_pool_new(void); +struct parsed_object_pool *parsed_object_pool_new(struct repository *repo); void parsed_object_pool_clear(struct parsed_object_pool *o); +void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o); struct object_list { struct object *item; @@ -47,7 +47,7 @@ void oidtree_insert(struct oidtree *ot, const struct object_id *oid) /* * n.b. Current callers won't get us duplicates, here. If a - * future caller causes duplicates, there'll be a a small leak + * future caller causes duplicates, there'll be a small leak * that won't be freed until oidtree_clear. Currently it's not * worth maintaining a free list */ diff --git a/oss-fuzz/.gitignore b/oss-fuzz/.gitignore index a877c11f42..f2d74de457 100644 --- a/oss-fuzz/.gitignore +++ b/oss-fuzz/.gitignore @@ -1,5 +1,8 @@ fuzz-commit-graph fuzz-config +fuzz-credential-from-url-gently fuzz-date fuzz-pack-headers fuzz-pack-idx +fuzz-parse-attr-line +fuzz-url-decode-mem diff --git a/oss-fuzz/dummy-cmd-main.c b/oss-fuzz/dummy-cmd-main.c index 071cb231ba..8ef776d06f 100644 --- a/oss-fuzz/dummy-cmd-main.c +++ b/oss-fuzz/dummy-cmd-main.c @@ -8,7 +8,7 @@ * executed. */ -int cmd_main(int argc, const char **argv) { +int cmd_main(int argc UNUSED, const char **argv UNUSED) { BUG("We should not execute cmd_main() from a fuzz target"); return 1; } diff --git a/oss-fuzz/fuzz-credential-from-url-gently.c b/oss-fuzz/fuzz-credential-from-url-gently.c new file mode 100644 index 0000000000..c872f9ad2d --- /dev/null +++ b/oss-fuzz/fuzz-credential-from-url-gently.c @@ -0,0 +1,32 @@ +#include "git-compat-util.h" +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include "credential.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct credential c; + char *buf; + + buf = malloc(size + 1); + if (!buf) + return 0; + + memcpy(buf, data, size); + buf[size] = 0; + + // start fuzzing + credential_init(&c); + credential_from_url_gently(&c, buf, 1); + + // cleanup + credential_clear(&c); + free(buf); + + return 0; +} diff --git a/oss-fuzz/fuzz-parse-attr-line.c b/oss-fuzz/fuzz-parse-attr-line.c new file mode 100644 index 0000000000..45a4c4e53c --- /dev/null +++ b/oss-fuzz/fuzz-parse-attr-line.c @@ -0,0 +1,39 @@ +#include "git-compat-util.h" +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include "attr.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct match_attr *res; + char *buf; + + buf = malloc(size + 1); + if (!buf) + return 0; + + memcpy(buf, data, size); + buf[size] = 0; + + res = parse_attr_line(buf, "dummy", 0, 0); + + if (res) { + int j; + for (j = 0; j < res->num_attr; j++) { + const char *setto = res->state[j].setto; + if (ATTR_TRUE(setto) || ATTR_FALSE(setto) || + ATTR_UNSET(setto)) + ; + else + free((char *)setto); + } + free(res); + } + free(buf); + + return 0; +} diff --git a/oss-fuzz/fuzz-url-decode-mem.c b/oss-fuzz/fuzz-url-decode-mem.c new file mode 100644 index 0000000000..2342aa993b --- /dev/null +++ b/oss-fuzz/fuzz-url-decode-mem.c @@ -0,0 +1,43 @@ +#include "git-compat-util.h" +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include "url.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char *buf; + char *r; + const char *pbuf; + + buf = malloc(size + 1); + if (!buf) + return 0; + + memcpy(buf, data, size); + buf[size] = 0; + + // start fuzzing + r = url_decode(buf); + free(r); + + r = url_percent_decode(buf); + free(r); + + pbuf = (const char*) buf; + r = url_decode_parameter_name(&pbuf); + free(r); + + pbuf = (const char*) buf; + r = url_decode_parameter_value(&pbuf); + free(r); + + // cleanup + free(buf); + + return 0; +} diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index bf96c80898..49758e2525 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -41,17 +41,19 @@ static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer return writer->selected_nr - writer->pseudo_merges_nr; } -void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r) +void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, + struct packing_data *pdata) { memset(writer, 0, sizeof(struct bitmap_writer)); if (writer->bitmaps) BUG("bitmap writer already initialized"); writer->bitmaps = kh_init_oid_map(); writer->pseudo_merge_commits = kh_init_oid_map(); + writer->to_pack = pdata; string_list_init_dup(&writer->pseudo_merge_groups); - load_pseudo_merges_from_config(&writer->pseudo_merge_groups); + load_pseudo_merges_from_config(r, &writer->pseudo_merge_groups); } static void free_pseudo_merge_commit_idx(struct pseudo_merge_commit_idx *idx) @@ -62,6 +64,12 @@ static void free_pseudo_merge_commit_idx(struct pseudo_merge_commit_idx *idx) free(idx); } +static void pseudo_merge_group_release_cb(void *payload, const char *name UNUSED) +{ + pseudo_merge_group_release(payload); + free(payload); +} + void bitmap_writer_free(struct bitmap_writer *writer) { uint32_t i; @@ -80,6 +88,8 @@ void bitmap_writer_free(struct bitmap_writer *writer) kh_foreach_value(writer->pseudo_merge_commits, idx, free_pseudo_merge_commit_idx(idx)); kh_destroy_oid_map(writer->pseudo_merge_commits); + string_list_clear_func(&writer->pseudo_merge_groups, + pseudo_merge_group_release_cb); for (i = 0; i < writer->selected_nr; i++) { struct bitmapped_commit *bc = &writer->selected[i]; @@ -99,9 +109,7 @@ void bitmap_writer_show_progress(struct bitmap_writer *writer, int show) * Build the initial type index for the packfile or multi-pack-index */ void bitmap_writer_build_type_index(struct bitmap_writer *writer, - struct packing_data *to_pack, - struct pack_idx_entry **index, - uint32_t index_nr) + struct pack_idx_entry **index) { uint32_t i; @@ -109,13 +117,13 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, writer->trees = ewah_new(); writer->blobs = ewah_new(); writer->tags = ewah_new(); - ALLOC_ARRAY(to_pack->in_pack_pos, to_pack->nr_objects); + ALLOC_ARRAY(writer->to_pack->in_pack_pos, writer->to_pack->nr_objects); - for (i = 0; i < index_nr; ++i) { + for (i = 0; i < writer->to_pack->nr_objects; ++i) { struct object_entry *entry = (struct object_entry *)index[i]; enum object_type real_type; - oe_set_in_pack_pos(to_pack, entry, i); + oe_set_in_pack_pos(writer->to_pack, entry, i); switch (oe_type(entry)) { case OBJ_COMMIT: @@ -126,7 +134,7 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, break; default: - real_type = oid_object_info(to_pack->repo, + real_type = oid_object_info(writer->to_pack->repo, &entry->idx.oid, NULL); break; } @@ -569,8 +577,7 @@ static void store_selected(struct bitmap_writer *writer, kh_value(writer->bitmaps, hash_pos) = stored; } -int bitmap_writer_build(struct bitmap_writer *writer, - struct packing_data *to_pack) +int bitmap_writer_build(struct bitmap_writer *writer) { struct bitmap_builder bb; size_t i; @@ -581,17 +588,15 @@ int bitmap_writer_build(struct bitmap_writer *writer, uint32_t *mapping; int closed = 1; /* until proven otherwise */ - writer->to_pack = to_pack; - if (writer->show_progress) writer->progress = start_progress("Building bitmaps", writer->selected_nr); trace2_region_enter("pack-bitmap-write", "building_bitmaps_total", the_repository); - old_bitmap = prepare_bitmap_git(to_pack->repo); + old_bitmap = prepare_bitmap_git(writer->to_pack->repo); if (old_bitmap) - mapping = create_bitmap_mapping(old_bitmap, to_pack); + mapping = create_bitmap_mapping(old_bitmap, writer->to_pack); else mapping = NULL; @@ -697,6 +702,9 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, if (indexed_commits_nr < 100) { for (i = 0; i < indexed_commits_nr; ++i) bitmap_writer_push_commit(writer, indexed_commits[i], 0); + + select_pseudo_merges(writer); + return; } @@ -737,7 +745,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, stop_progress(&writer->progress); - select_pseudo_merges(writer, indexed_commits, indexed_commits_nr); + select_pseudo_merges(writer); } @@ -905,6 +913,7 @@ static void write_pseudo_merges(struct bitmap_writer *writer, for (i = 0; i < writer->pseudo_merges_nr; i++) bitmap_free(commits_bitmap[i]); + oid_array_clear(&commits); free(pseudo_merge_ofs); free(commits_bitmap); } @@ -1001,7 +1010,6 @@ void bitmap_writer_set_checksum(struct bitmap_writer *writer, void bitmap_writer_finish(struct bitmap_writer *writer, struct pack_idx_entry **index, - uint32_t index_nr, const char *filename, uint16_t options) { @@ -1034,12 +1042,13 @@ void bitmap_writer_finish(struct bitmap_writer *writer, dump_bitmap(f, writer->tags); if (options & BITMAP_OPT_LOOKUP_TABLE) - CALLOC_ARRAY(offsets, index_nr); + CALLOC_ARRAY(offsets, writer->to_pack->nr_objects); for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) { struct bitmapped_commit *stored = &writer->selected[i]; int commit_pos = oid_pos(&stored->commit->object.oid, index, - index_nr, oid_access); + writer->to_pack->nr_objects, + oid_access); if (commit_pos < 0) BUG(_("trying to write commit not in index")); @@ -1055,7 +1064,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, write_lookup_table(writer, f, offsets); if (options & BITMAP_OPT_HASH_CACHE) - write_hash_cache(f, index, index_nr); + write_hash_cache(f, index, writer->to_pack->nr_objects); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); diff --git a/pack-bitmap.c b/pack-bitmap.c index 2e657a2aa4..7aa2410d9b 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "commit.h" #include "gettext.h" @@ -177,12 +175,21 @@ static uint32_t bitmap_num_objects(struct bitmap_index *index) return index->pack->num_objects; } +static struct repository *bitmap_repo(struct bitmap_index *bitmap_git) +{ + if (bitmap_is_midx(bitmap_git)) + return bitmap_git->midx->repo; + return bitmap_git->pack->repo; +} + static int load_bitmap_header(struct bitmap_index *index) { struct bitmap_disk_header *header = (void *)index->map; - size_t header_size = sizeof(*header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz; + const struct git_hash_algo *hash_algo = bitmap_repo(index)->hash_algo; + + size_t header_size = sizeof(*header) - GIT_MAX_RAWSZ + hash_algo->rawsz; - if (index->map_size < header_size + the_hash_algo->rawsz) + if (index->map_size < header_size + hash_algo->rawsz) return error(_("corrupted bitmap index (too small)")); if (memcmp(header->magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE)) != 0) @@ -196,7 +203,7 @@ static int load_bitmap_header(struct bitmap_index *index) { uint32_t flags = ntohs(header->options); size_t cache_size = st_mult(bitmap_num_objects(index), sizeof(uint32_t)); - unsigned char *index_end = index->map + index->map_size - the_hash_algo->rawsz; + unsigned char *index_end = index->map + index->map_size - hash_algo->rawsz; if ((flags & BITMAP_OPT_FULL_DAG) == 0) BUG("unsupported options for bitmap index file " @@ -368,8 +375,8 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) char *midx_bitmap_filename(struct multi_pack_index *midx) { struct strbuf buf = STRBUF_INIT; - get_midx_filename_ext(&buf, midx->object_dir, get_midx_checksum(midx), - MIDX_EXT_BITMAP); + get_midx_filename_ext(midx->repo->hash_algo, &buf, midx->object_dir, + get_midx_checksum(midx), MIDX_EXT_BITMAP); return strbuf_detach(&buf, NULL); } @@ -408,8 +415,8 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git, if (bitmap_git->pack || bitmap_git->midx) { struct strbuf buf = STRBUF_INIT; - get_midx_filename(&buf, midx->object_dir); - trace2_data_string("bitmap", the_repository, + get_midx_filename(midx->repo->hash_algo, &buf, midx->object_dir); + trace2_data_string("bitmap", bitmap_repo(bitmap_git), "ignoring extra midx bitmap file", buf.buf); close(fd); strbuf_release(&buf); @@ -427,7 +434,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git, goto cleanup; if (!hasheq(get_midx_checksum(bitmap_git->midx), bitmap_git->checksum, - the_repository->hash_algo)) { + bitmap_repo(bitmap_git)->hash_algo)) { error(_("checksum doesn't match in MIDX and bitmap")); goto cleanup; } @@ -438,7 +445,9 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git, } for (i = 0; i < bitmap_git->midx->num_packs; i++) { - if (prepare_midx_pack(the_repository, bitmap_git->midx, i)) { + if (prepare_midx_pack(bitmap_repo(bitmap_git), + bitmap_git->midx, + i)) { warning(_("could not open pack %s"), bitmap_git->midx->pack_names[i]); goto cleanup; @@ -492,8 +501,9 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git } if (bitmap_git->pack || bitmap_git->midx) { - trace2_data_string("bitmap", the_repository, - "ignoring extra bitmap file", packfile->pack_name); + trace2_data_string("bitmap", bitmap_repo(bitmap_git), + "ignoring extra bitmap file", + packfile->pack_name); close(fd); return -1; } @@ -518,8 +528,8 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git return -1; } - trace2_data_string("bitmap", the_repository, "opened bitmap file", - packfile->pack_name); + trace2_data_string("bitmap", bitmap_repo(bitmap_git), + "opened bitmap file", packfile->pack_name); return 0; } @@ -649,7 +659,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r) struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx) { - struct repository *r = the_repository; + struct repository *r = midx->repo; struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git)); if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git)) @@ -935,7 +945,7 @@ static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git, const struct object_id *oid) { uint32_t pos; - off_t offset = find_pack_entry_one(oid->hash, bitmap_git->pack); + off_t offset = find_pack_entry_one(oid, bitmap_git->pack); if (!offset) return -1; @@ -1213,6 +1223,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, { struct bitmap_boundary_cb cb; struct object_list *root; + struct repository *repo; unsigned int i; unsigned int tmp_blobs, tmp_trees, tmp_tags; int any_missing = 0; @@ -1222,6 +1233,8 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, cb.base = bitmap_new(); object_array_init(&cb.boundary); + repo = bitmap_repo(bitmap_git); + revs->ignore_missing_links = 1; if (bitmap_git->pseudo_merges.nr) { @@ -1270,7 +1283,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, tmp_blobs = revs->blob_objects; tmp_trees = revs->tree_objects; - tmp_tags = revs->blob_objects; + tmp_tags = revs->tag_objects; revs->blob_objects = 0; revs->tree_objects = 0; revs->tag_objects = 0; @@ -1280,19 +1293,19 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, * revision walk to (a) OR in any bitmaps that are UNINTERESTING * between the tips and boundary, and (b) record the boundary. */ - trace2_region_enter("pack-bitmap", "boundary-prepare", the_repository); + trace2_region_enter("pack-bitmap", "boundary-prepare", repo); if (prepare_revision_walk(revs)) die("revision walk setup failed"); - trace2_region_leave("pack-bitmap", "boundary-prepare", the_repository); + trace2_region_leave("pack-bitmap", "boundary-prepare", repo); - trace2_region_enter("pack-bitmap", "boundary-traverse", the_repository); + trace2_region_enter("pack-bitmap", "boundary-traverse", repo); revs->boundary = 1; traverse_commit_list_filtered(revs, show_boundary_commit, show_boundary_object, &cb, NULL); revs->boundary = 0; - trace2_region_leave("pack-bitmap", "boundary-traverse", the_repository); + trace2_region_leave("pack-bitmap", "boundary-traverse", repo); revs->blob_objects = tmp_blobs; revs->tree_objects = tmp_trees; @@ -1304,7 +1317,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, /* * Then add the boundary commit(s) as fill-in traversal tips. */ - trace2_region_enter("pack-bitmap", "boundary-fill-in", the_repository); + trace2_region_enter("pack-bitmap", "boundary-fill-in", repo); for (i = 0; i < cb.boundary.nr; i++) { struct object *obj = cb.boundary.objects[i].item; if (bitmap_walk_contains(bitmap_git, cb.base, &obj->oid)) @@ -1314,7 +1327,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, } if (revs->pending.nr) cb.base = fill_in_bitmap(bitmap_git, revs, cb.base, NULL); - trace2_region_leave("pack-bitmap", "boundary-fill-in", the_repository); + trace2_region_leave("pack-bitmap", "boundary-fill-in", repo); cleanup: object_array_clear(&cb.boundary); @@ -1390,8 +1403,8 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git, } base = bitmap_new(); - if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap)) - bitmap_free(roots_bitmap); + cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap); + bitmap_free(roots_bitmap); } /* @@ -1609,7 +1622,7 @@ static int in_bitmapped_pack(struct bitmap_index *bitmap_git, if (bsearch_midx(&object->oid, bitmap_git->midx, NULL)) return 1; } else { - if (find_pack_entry_one(object->oid.hash, bitmap_git->pack) > 0) + if (find_pack_entry_one(&object->oid, bitmap_git->pack) > 0) return 1; } } @@ -1718,7 +1731,8 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git, ofs = pack_pos_to_offset(pack, pos); } - if (packed_object_info(the_repository, pack, ofs, &oi) < 0) { + if (packed_object_info(bitmap_repo(bitmap_git), pack, ofs, + &oi) < 0) { struct object_id oid; nth_bitmap_object_oid(bitmap_git, &oid, pack_pos_to_index(pack, pos)); @@ -1727,7 +1741,8 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git, } else { struct eindex *eindex = &bitmap_git->ext_index; struct object *obj = eindex->objects[pos - bitmap_num_objects(bitmap_git)]; - if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0) + if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid, + &oi, 0) < 0) die(_("unable to get size of %s"), oid_to_hex(&obj->oid)); } @@ -1889,7 +1904,8 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git, bitmap_unset(result, i); for (i = 0; i < eindex->count; ++i) { - if (has_object_pack(&eindex->objects[i]->oid)) + if (has_object_pack(bitmap_repo(bitmap_git), + &eindex->objects[i]->oid)) bitmap_unset(result, objects_nr + i); } } @@ -1907,6 +1923,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, struct bitmap *haves_bitmap = NULL; struct bitmap_index *bitmap_git; + struct repository *repo; /* * We can't do pathspec limiting with bitmaps, because we don't know @@ -1980,18 +1997,20 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, if (!use_boundary_traversal) object_array_clear(&revs->pending); + repo = bitmap_repo(bitmap_git); + if (haves) { if (use_boundary_traversal) { - trace2_region_enter("pack-bitmap", "haves/boundary", the_repository); + trace2_region_enter("pack-bitmap", "haves/boundary", repo); haves_bitmap = find_boundary_objects(bitmap_git, revs, haves); - trace2_region_leave("pack-bitmap", "haves/boundary", the_repository); + trace2_region_leave("pack-bitmap", "haves/boundary", repo); } else { - trace2_region_enter("pack-bitmap", "haves/classic", the_repository); + trace2_region_enter("pack-bitmap", "haves/classic", repo); revs->ignore_missing_links = 1; haves_bitmap = find_objects(bitmap_git, revs, haves, NULL); reset_revision_walk(); revs->ignore_missing_links = 0; - trace2_region_leave("pack-bitmap", "haves/classic", the_repository); + trace2_region_leave("pack-bitmap", "haves/classic", repo); } if (!haves_bitmap) @@ -2025,17 +2044,17 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, object_list_free(&wants); object_list_free(&haves); - trace2_data_intmax("bitmap", the_repository, "pseudo_merges_satisfied", + trace2_data_intmax("bitmap", repo, "pseudo_merges_satisfied", pseudo_merges_satisfied_nr); - trace2_data_intmax("bitmap", the_repository, "pseudo_merges_cascades", + trace2_data_intmax("bitmap", repo, "pseudo_merges_cascades", pseudo_merges_cascades_nr); - trace2_data_intmax("bitmap", the_repository, "bitmap/hits", + trace2_data_intmax("bitmap", repo, "bitmap/hits", existing_bitmaps_hits_nr); - trace2_data_intmax("bitmap", the_repository, "bitmap/misses", + trace2_data_intmax("bitmap", repo, "bitmap/misses", existing_bitmaps_misses_nr); - trace2_data_intmax("bitmap", the_repository, "bitmap/roots_with_bitmap", + trace2_data_intmax("bitmap", repo, "bitmap/roots_with_bitmap", roots_with_bitmaps_nr); - trace2_data_intmax("bitmap", the_repository, "bitmap/roots_without_bitmap", + trace2_data_intmax("bitmap", repo, "bitmap/roots_without_bitmap", roots_without_bitmaps_nr); return bitmap_git; @@ -2055,17 +2074,18 @@ static int try_partial_reuse(struct bitmap_index *bitmap_git, struct bitmapped_pack *pack, size_t bitmap_pos, uint32_t pack_pos, + off_t offset, struct bitmap *reuse, struct pack_window **w_curs) { - off_t offset, delta_obj_offset; + off_t delta_obj_offset; enum object_type type; unsigned long size; if (pack_pos >= pack->p->num_objects) return -1; /* not actually in the pack */ - offset = delta_obj_offset = pack_pos_to_offset(pack->p, pack_pos); + delta_obj_offset = offset; type = unpack_object_header(pack->p, w_curs, &offset, &size); if (type < 0) return -1; /* broken packfile, punt */ @@ -2184,6 +2204,7 @@ static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git for (offset = 0; offset < BITS_IN_EWORD; offset++) { size_t bit_pos; uint32_t pack_pos; + off_t ofs; if (word >> offset == 0) break; @@ -2198,7 +2219,6 @@ static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git if (bitmap_is_midx(bitmap_git)) { uint32_t midx_pos; - off_t ofs; midx_pos = pack_pos_to_midx(bitmap_git->midx, bit_pos); ofs = nth_midxed_offset(bitmap_git->midx, midx_pos); @@ -2213,10 +2233,12 @@ static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git BUG("advanced beyond the end of pack %s (%"PRIuMAX" > %"PRIu32")", pack_basename(pack->p), (uintmax_t)pack_pos, pack->p->num_objects); + + ofs = pack_pos_to_offset(pack->p, pack_pos); } if (try_partial_reuse(bitmap_git, pack, bit_pos, - pack_pos, reuse, &w_curs) < 0) { + pack_pos, ofs, reuse, &w_curs) < 0) { /* * try_partial_reuse indicated we couldn't reuse * any bits, so there is no point in trying more @@ -2253,7 +2275,7 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, struct bitmap **reuse_out, int multi_pack_reuse) { - struct repository *r = the_repository; + struct repository *r = bitmap_repo(bitmap_git); struct bitmapped_pack *packs = NULL; struct bitmap *result = bitmap_git->result; struct bitmap *reuse; @@ -2322,6 +2344,7 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, packs[packs_nr].pack_int_id = pack_int_id; packs[packs_nr].bitmap_nr = pack->num_objects; packs[packs_nr].bitmap_pos = 0; + packs[packs_nr].from_midx = bitmap_git->midx; objects_nr = packs[packs_nr++].bitmap_nr; } @@ -2788,7 +2811,7 @@ int rebuild_bitmap(const uint32_t *reposition, uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git, struct packing_data *mapping) { - struct repository *r = the_repository; + struct repository *r = bitmap_repo(bitmap_git); uint32_t i, num_objects; uint32_t *reposition; @@ -2944,7 +2967,8 @@ static off_t get_disk_usage_for_extended(struct bitmap_index *bitmap_git) st_add(bitmap_num_objects(bitmap_git), i))) continue; - if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0) + if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid, + &oi, 0) < 0) die(_("unable to get disk usage of '%s'"), oid_to_hex(&obj->oid)); diff --git a/pack-bitmap.h b/pack-bitmap.h index 1171e6d989..d7f4b8b8e9 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -60,6 +60,7 @@ struct bitmapped_pack { uint32_t bitmap_pos; uint32_t bitmap_nr; + struct multi_pack_index *from_midx; /* MIDX only */ uint32_t pack_int_id; /* MIDX only */ }; @@ -123,14 +124,13 @@ struct bitmap_writer { unsigned char pack_checksum[GIT_MAX_RAWSZ]; }; -void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r); +void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, + struct packing_data *pdata); void bitmap_writer_show_progress(struct bitmap_writer *writer, int show); void bitmap_writer_set_checksum(struct bitmap_writer *writer, const unsigned char *sha1); void bitmap_writer_build_type_index(struct bitmap_writer *writer, - struct packing_data *to_pack, - struct pack_idx_entry **index, - uint32_t index_nr); + struct pack_idx_entry **index); int bitmap_writer_has_bitmapped_object_id(struct bitmap_writer *writer, const struct object_id *oid); void bitmap_writer_push_commit(struct bitmap_writer *writer, @@ -147,11 +147,9 @@ struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_g void bitmap_writer_select_commits(struct bitmap_writer *writer, struct commit **indexed_commits, unsigned int indexed_commits_nr); -int bitmap_writer_build(struct bitmap_writer *writer, - struct packing_data *to_pack); +int bitmap_writer_build(struct bitmap_writer *writer); void bitmap_writer_finish(struct bitmap_writer *writer, struct pack_idx_entry **index, - uint32_t index_nr, const char *filename, uint16_t options); void bitmap_writer_free(struct bitmap_writer *writer); diff --git a/pack-objects.h b/pack-objects.h index b9898a4e64..3f6f504203 100644 --- a/pack-objects.h +++ b/pack-objects.h @@ -7,7 +7,8 @@ struct repository; -#define DEFAULT_DELTA_CACHE_SIZE (256 * 1024 * 1024) +#define DEFAULT_DELTA_CACHE_SIZE (256 * 1024 * 1024) +#define DEFAULT_DELTA_BASE_CACHE_LIMIT (96 * 1024 * 1024) #define OE_DFS_STATE_BITS 2 #define OE_DEPTH_BITS 12 diff --git a/pack-revindex.c b/pack-revindex.c index 22d3c23464..d3832478d9 100644 --- a/pack-revindex.c +++ b/pack-revindex.c @@ -383,7 +383,7 @@ int load_midx_revindex(struct multi_pack_index *m) trace2_data_string("load_midx_revindex", the_repository, "source", "rev"); - get_midx_filename_ext(&revindex_name, m->object_dir, + get_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir, get_midx_checksum(m), MIDX_EXT_REV); ret = load_revindex_from_disk(revindex_name.buf, diff --git a/pack-write.c b/pack-write.c index d07f03d0ab..98a8c0e785 100644 --- a/pack-write.c +++ b/pack-write.c @@ -8,10 +8,12 @@ #include "csum-file.h" #include "remote.h" #include "chunk-format.h" +#include "object-file.h" #include "pack-mtimes.h" #include "pack-objects.h" #include "pack-revindex.h" #include "path.h" +#include "repository.h" #include "strbuf.h" void reset_pack_idx_option(struct pack_idx_option *opts) @@ -19,6 +21,7 @@ void reset_pack_idx_option(struct pack_idx_option *opts) memset(opts, 0, sizeof(*opts)); opts->version = 2; opts->off32_limit = 0x7fffffff; + opts->delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT; } static int sha1_compare(const void *_a, const void *_b) @@ -211,15 +214,15 @@ static void write_rev_trailer(struct hashfile *f, const unsigned char *hash) hashwrite(f, hash, the_hash_algo->rawsz); } -const char *write_rev_file(const char *rev_name, - struct pack_idx_entry **objects, - uint32_t nr_objects, - const unsigned char *hash, - unsigned flags) +char *write_rev_file(const char *rev_name, + struct pack_idx_entry **objects, + uint32_t nr_objects, + const unsigned char *hash, + unsigned flags) { uint32_t *pack_order; uint32_t i; - const char *ret; + char *ret; if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY)) return NULL; @@ -237,13 +240,14 @@ const char *write_rev_file(const char *rev_name, return ret; } -const char *write_rev_file_order(const char *rev_name, - uint32_t *pack_order, - uint32_t nr_objects, - const unsigned char *hash, - unsigned flags) +char *write_rev_file_order(const char *rev_name, + uint32_t *pack_order, + uint32_t nr_objects, + const unsigned char *hash, + unsigned flags) { struct hashfile *f; + char *path; int fd; if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY)) @@ -253,12 +257,13 @@ const char *write_rev_file_order(const char *rev_name, if (!rev_name) { struct strbuf tmp_file = STRBUF_INIT; fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX"); - rev_name = strbuf_detach(&tmp_file, NULL); + path = strbuf_detach(&tmp_file, NULL); } else { unlink(rev_name); fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600); + path = xstrdup(rev_name); } - f = hashfd(fd, rev_name); + f = hashfd(fd, path); } else if (flags & WRITE_REV_VERIFY) { struct stat statbuf; if (stat(rev_name, &statbuf)) { @@ -269,22 +274,24 @@ const char *write_rev_file_order(const char *rev_name, die_errno(_("could not stat: %s"), rev_name); } f = hashfd_check(rev_name); - } else + path = xstrdup(rev_name); + } else { return NULL; + } write_rev_header(f); write_rev_index_positions(f, pack_order, nr_objects); write_rev_trailer(f, hash); - if (rev_name && adjust_shared_perm(rev_name) < 0) - die(_("failed to make %s readable"), rev_name); + if (adjust_shared_perm(path) < 0) + die(_("failed to make %s readable"), path); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_CLOSE | ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC)); - return rev_name; + return path; } static void write_mtimes_header(struct hashfile *f) @@ -473,7 +480,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed) packname[len-1] = 0; if (skip_prefix(packname, "keep\t", &name)) return xstrfmt("%s/pack/pack-%s.keep", - get_object_directory(), name); + repo_get_object_directory(the_repository), name); return NULL; } if (is_well_formed) @@ -527,9 +534,9 @@ static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source, size_t name_prefix_len = name_prefix->len; strbuf_addstr(name_prefix, ext); - if (rename(source, name_prefix->buf)) - die_errno("unable to rename temporary file to '%s'", - name_prefix->buf); + if (finalize_object_file(source, name_prefix->buf)) + die("unable to rename temporary file to '%s'", + name_prefix->buf); strbuf_setlen(name_prefix, name_prefix_len); } @@ -548,7 +555,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer, unsigned char hash[], char **idx_tmp_name) { - const char *rev_tmp_name = NULL; + char *rev_tmp_name = NULL; char *mtimes_tmp_name = NULL; if (adjust_shared_perm(pack_tmp_name)) @@ -574,7 +581,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer, if (mtimes_tmp_name) rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes"); - free((char *)rev_tmp_name); + free(rev_tmp_name); free(mtimes_tmp_name); } @@ -58,6 +58,8 @@ struct pack_idx_option { */ int anomaly_alloc, anomaly_nr; uint32_t *anomaly; + + size_t delta_base_cache_limit; }; void reset_pack_idx_option(struct pack_idx_option *); @@ -96,8 +98,8 @@ struct ref; void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought); -const char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags); -const char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags); +char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags); +char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags); /* * The "hdr" output buffer should be at least this big, which will handle sizes diff --git a/packfile.c b/packfile.c index 813584646f..9c4bd81a8c 100644 --- a/packfile.c +++ b/packfile.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "environment.h" @@ -25,28 +24,15 @@ #include "pack-revindex.h" #include "promisor-remote.h" -char *odb_pack_name(struct strbuf *buf, - const unsigned char *hash, - const char *ext) +char *odb_pack_name(struct repository *r, struct strbuf *buf, + const unsigned char *hash, const char *ext) { strbuf_reset(buf); - strbuf_addf(buf, "%s/pack/pack-%s.%s", get_object_directory(), - hash_to_hex(hash), ext); + strbuf_addf(buf, "%s/pack/pack-%s.%s", repo_get_object_directory(r), + hash_to_hex_algop(hash, r->hash_algo), ext); return buf->buf; } -char *sha1_pack_name(const unsigned char *sha1) -{ - static struct strbuf buf = STRBUF_INIT; - return odb_pack_name(&buf, sha1, "pack"); -} - -char *sha1_pack_index_name(const unsigned char *sha1) -{ - static struct strbuf buf = STRBUF_INIT; - return odb_pack_name(&buf, sha1, "idx"); -} - static unsigned int pack_used_ctr; static unsigned int pack_mmap_calls; static unsigned int peak_pack_open_windows; @@ -59,15 +45,15 @@ static size_t pack_mapped; #define SZ_FMT PRIuMAX static inline uintmax_t sz_fmt(size_t s) { return s; } -void pack_report(void) +void pack_report(struct repository *repo) { fprintf(stderr, "pack_report: getpagesize() = %10" SZ_FMT "\n" "pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n" "pack_report: core.packedGitLimit = %10" SZ_FMT "\n", sz_fmt(getpagesize()), - sz_fmt(packed_git_window_size), - sz_fmt(packed_git_limit)); + sz_fmt(repo->settings.packed_git_window_size), + sz_fmt(repo->settings.packed_git_limit)); fprintf(stderr, "pack_report: pack_used_ctr = %10u\n" "pack_report: pack_mmap_calls = %10u\n" @@ -91,7 +77,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p) size_t idx_size; int fd = git_open(path), ret; struct stat st; - const unsigned int hashsz = the_hash_algo->rawsz; + const unsigned int hashsz = p->repo->hash_algo->rawsz; if (fd < 0) return -1; @@ -229,22 +215,33 @@ uint32_t get_pack_fanout(struct packed_git *p, uint32_t value) return ntohl(level1_ofs[value]); } -static struct packed_git *alloc_packed_git(int extra) +static struct packed_git *alloc_packed_git(struct repository *r, int extra) { struct packed_git *p = xmalloc(st_add(sizeof(*p), extra)); memset(p, 0, sizeof(*p)); p->pack_fd = -1; + p->repo = r; return p; } -struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path) +static char *pack_path_from_idx(const char *idx_path) { - const char *path = sha1_pack_name(sha1); + size_t len; + if (!strip_suffix(idx_path, ".idx", &len)) + BUG("idx path does not end in .idx: %s", idx_path); + return xstrfmt("%.*s.pack", (int)len, idx_path); +} + +struct packed_git *parse_pack_index(struct repository *r, unsigned char *sha1, + const char *idx_path) +{ + char *path = pack_path_from_idx(idx_path); size_t alloc = st_add(strlen(path), 1); - struct packed_git *p = alloc_packed_git(alloc); + struct packed_git *p = alloc_packed_git(r, alloc); memcpy(p->pack_name, path, alloc); /* includes NUL */ - hashcpy(p->hash, sha1, the_repository->hash_algo); + free(path); + hashcpy(p->hash, sha1, p->repo->hash_algo); if (check_packed_git_idx(idx_path, p)) { free(p); return NULL; @@ -279,7 +276,7 @@ static int unuse_one_window(struct packed_git *current) if (current) scan_windows(current, &lru_p, &lru_w, &lru_l); - for (p = the_repository->objects->packed_git; p; p = p->next) + for (p = current->repo->objects->packed_git; p; p = p->next) scan_windows(p, &lru_p, &lru_w, &lru_l); if (lru_p) { munmap(lru_w->base, lru_w->len); @@ -461,13 +458,13 @@ static void find_lru_pack(struct packed_git *p, struct packed_git **lru_p, struc *accept_windows_inuse = has_windows_inuse; } -static int close_one_pack(void) +static int close_one_pack(struct repository *r) { struct packed_git *p, *lru_p = NULL; struct pack_window *mru_w = NULL; int accept_windows_inuse = 1; - for (p = the_repository->objects->packed_git; p; p = p->next) { + for (p = r->objects->packed_git; p; p = p->next) { if (p->pack_fd == -1) continue; find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse); @@ -541,7 +538,7 @@ static int open_packed_git_1(struct packed_git *p) unsigned char hash[GIT_MAX_RAWSZ]; unsigned char *idx_hash; ssize_t read_result; - const unsigned hashsz = the_hash_algo->rawsz; + const unsigned hashsz = p->repo->hash_algo->rawsz; if (open_pack_index(p)) return error("packfile %s index unavailable", p->pack_name); @@ -556,7 +553,7 @@ static int open_packed_git_1(struct packed_git *p) pack_max_fds = 1; } - while (pack_max_fds <= pack_open_fds && close_one_pack()) + while (pack_max_fds <= pack_open_fds && close_one_pack(p->repo)) ; /* nothing */ p->pack_fd = git_open(p->pack_name); @@ -598,7 +595,7 @@ static int open_packed_git_1(struct packed_git *p) if (read_result != hashsz) return error("packfile %s signature is unavailable", p->pack_name); idx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2; - if (!hasheq(hash, idx_hash, the_repository->hash_algo)) + if (!hasheq(hash, idx_hash, p->repo->hash_algo)) return error("packfile %s does not match index", p->pack_name); return 0; } @@ -611,7 +608,8 @@ static int open_packed_git(struct packed_git *p) return -1; } -static int in_window(struct pack_window *win, off_t offset) +static int in_window(struct repository *r, struct pack_window *win, + off_t offset) { /* We must promise at least one full hash after the * offset is available from this window, otherwise the offset @@ -621,7 +619,7 @@ static int in_window(struct pack_window *win, off_t offset) */ off_t win_off = win->offset; return win_off <= offset - && (offset + the_hash_algo->rawsz) <= (win_off + win->len); + && (offset + r->hash_algo->rawsz) <= (win_off + win->len); } unsigned char *use_pack(struct packed_git *p, @@ -638,21 +636,28 @@ unsigned char *use_pack(struct packed_git *p, */ if (!p->pack_size && p->pack_fd == -1 && open_packed_git(p)) die("packfile %s cannot be accessed", p->pack_name); - if (offset > (p->pack_size - the_hash_algo->rawsz)) + if (offset > (p->pack_size - p->repo->hash_algo->rawsz)) die("offset beyond end of packfile (truncated pack?)"); if (offset < 0) die(_("offset before end of packfile (broken .idx?)")); - if (!win || !in_window(win, offset)) { + if (!win || !in_window(p->repo, win, offset)) { if (win) win->inuse_cnt--; for (win = p->windows; win; win = win->next) { - if (in_window(win, offset)) + if (in_window(p->repo, win, offset)) break; } if (!win) { - size_t window_align = packed_git_window_size / 2; + size_t window_align; off_t len; + struct repo_settings *settings; + + /* lazy load the settings in case it hasn't been setup */ + prepare_repo_settings(p->repo); + settings = &p->repo->settings; + + window_align = settings->packed_git_window_size / 2; if (p->pack_fd == -1 && open_packed_git(p)) die("packfile %s cannot be accessed", p->pack_name); @@ -660,11 +665,12 @@ unsigned char *use_pack(struct packed_git *p, CALLOC_ARRAY(win, 1); win->offset = (offset / window_align) * window_align; len = p->pack_size - win->offset; - if (len > packed_git_window_size) - len = packed_git_window_size; + if (len > settings->packed_git_window_size) + len = settings->packed_git_window_size; win->len = (size_t)len; pack_mapped += win->len; - while (packed_git_limit < pack_mapped + + while (settings->packed_git_limit < pack_mapped && unuse_one_window(p)) ; /* nothing */ win->base = xmmap_gently(NULL, win->len, @@ -706,11 +712,13 @@ void unuse_pack(struct pack_window **w_cursor) } } -struct packed_git *add_packed_git(const char *path, size_t path_len, int local) +struct packed_git *add_packed_git(struct repository *r, const char *path, + size_t path_len, int local) { struct stat st; size_t alloc; struct packed_git *p; + struct object_id oid; /* * Make sure a corresponding .pack file exists and that @@ -724,7 +732,7 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local) * the use xsnprintf double-checks that) */ alloc = st_add3(path_len, strlen(".promisor"), 1); - p = alloc_packed_git(alloc); + p = alloc_packed_git(r, alloc); memcpy(p->pack_name, path, path_len); xsnprintf(p->pack_name + path_len, alloc - path_len, ".keep"); @@ -751,9 +759,13 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local) p->pack_size = st.st_size; p->pack_local = local; p->mtime = st.st_mtime; - if (path_len < the_hash_algo->hexsz || - get_hash_hex(path + path_len - the_hash_algo->hexsz, p->hash)) - hashclr(p->hash, the_repository->hash_algo); + if (path_len < r->hash_algo->hexsz || + get_oid_hex_algop(path + path_len - r->hash_algo->hexsz, &oid, + r->hash_algo)) + hashclr(p->hash, r->hash_algo); + else + hashcpy(p->hash, oid.hash, r->hash_algo); + return p; } @@ -815,9 +827,10 @@ static void report_pack_garbage(struct string_list *list) report_helper(list, seen_bits, first, list->nr); } -void for_each_file_in_pack_dir(const char *objdir, - each_file_in_pack_dir_fn fn, - void *data) +void for_each_file_in_pack_subdir(const char *objdir, + const char *subdir, + each_file_in_pack_dir_fn fn, + void *data) { struct strbuf path = STRBUF_INIT; size_t dirnamelen; @@ -826,6 +839,8 @@ void for_each_file_in_pack_dir(const char *objdir, strbuf_addstr(&path, objdir); strbuf_addstr(&path, "/pack"); + if (subdir) + strbuf_addf(&path, "/%s", subdir); dir = opendir(path.buf); if (!dir) { if (errno != ENOENT) @@ -847,6 +862,13 @@ void for_each_file_in_pack_dir(const char *objdir, strbuf_release(&path); } +void for_each_file_in_pack_dir(const char *objdir, + each_file_in_pack_dir_fn fn, + void *data) +{ + for_each_file_in_pack_subdir(objdir, NULL, fn, data); +} + struct prepare_pack_data { struct repository *r; struct string_list *garbage; @@ -870,7 +892,7 @@ static void prepare_pack(const char *full_name, size_t full_name_len, /* Don't reopen a pack we already have. */ if (!hashmap_get(&data->r->objects->pack_map, &hent, pack_name)) { - p = add_packed_git(full_name, full_name_len, data->local); + p = add_packed_git(data->r, full_name, full_name_len, data->local); if (p) install_packed_git(data->r, p); } @@ -880,7 +902,8 @@ static void prepare_pack(const char *full_name, size_t full_name_len, if (!report_garbage) return; - if (!strcmp(file_name, "multi-pack-index")) + if (!strcmp(file_name, "multi-pack-index") || + !strcmp(file_name, "multi-pack-index.d")) return; if (starts_with(file_name, "multi-pack-index") && (ends_with(file_name, ".bitmap") || ends_with(file_name, ".rev"))) @@ -1064,7 +1087,7 @@ struct packed_git *get_all_packs(struct repository *r) prepare_packed_git(r); for (m = r->objects->multi_pack_index; m; m = m->next) { uint32_t i; - for (i = 0; i < m->num_packs; i++) + for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) prepare_midx_pack(r, m, i); } @@ -1231,8 +1254,10 @@ off_t get_delta_base(struct packed_git *p, *curpos += used; } else if (type == OBJ_REF_DELTA) { /* The base entry _must_ be in the same pack */ - base_offset = find_pack_entry_one(base_info, p); - *curpos += the_hash_algo->rawsz; + struct object_id oid; + oidread(&oid, base_info, p->repo->hash_algo); + base_offset = find_pack_entry_one(&oid, p); + *curpos += p->repo->hash_algo->rawsz; } else die("I am totally screwed"); return base_offset; @@ -1253,7 +1278,7 @@ static int get_delta_base_oid(struct packed_git *p, { if (type == OBJ_REF_DELTA) { unsigned char *base = use_pack(p, w_curs, curpos, NULL); - oidread(oid, base, the_repository->hash_algo); + oidread(oid, base, p->repo->hash_algo); return 0; } else if (type == OBJ_OFS_DELTA) { uint32_t base_pos; @@ -1478,7 +1503,9 @@ void clear_delta_base_cache(void) } static void add_delta_base_cache(struct packed_git *p, off_t base_offset, - void *base, unsigned long base_size, enum object_type type) + void *base, unsigned long base_size, + unsigned long delta_base_cache_limit, + enum object_type type) { struct delta_base_cache_entry *ent; struct list_head *lru, *tmp; @@ -1595,7 +1622,7 @@ int packed_object_info(struct repository *r, struct packed_git *p, goto out; } } else - oidclr(oi->delta_base_oid, the_repository->hash_algo); + oidclr(oi->delta_base_oid, p->repo->hash_algo); } oi->whence = in_delta_base_cache(p, obj_offset) ? OI_DBCACHED : @@ -1680,6 +1707,8 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset, int delta_stack_nr = 0, delta_stack_alloc = UNPACK_ENTRY_STACK_PREALLOC; int base_from_cache = 0; + prepare_repo_settings(p->repo); + write_pack_access_log(p, obj_offset); /* PHASE 1: drill down to the innermost base object */ @@ -1860,7 +1889,9 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset, * before we are done using it. */ if (!external_base) - add_delta_base_cache(p, base_obj_offset, base, base_size, type); + add_delta_base_cache(p, base_obj_offset, base, base_size, + p->repo->settings.delta_base_cache_limit, + type); free(delta_data); free(external_base); @@ -1884,7 +1915,7 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32 { const unsigned char *index_fanout = p->index_data; const unsigned char *index_lookup; - const unsigned int hashsz = the_hash_algo->rawsz; + const unsigned int hashsz = p->repo->hash_algo->rawsz; int index_lookup_width; if (!index_fanout) @@ -1909,7 +1940,7 @@ int nth_packed_object_id(struct object_id *oid, uint32_t n) { const unsigned char *index = p->index_data; - const unsigned int hashsz = the_hash_algo->rawsz; + const unsigned int hashsz = p->repo->hash_algo->rawsz; if (!index) { if (open_pack_index(p)) return -1; @@ -1920,11 +1951,10 @@ int nth_packed_object_id(struct object_id *oid, index += 4 * 256; if (p->index_version == 1) { oidread(oid, index + st_add(st_mult(hashsz + 4, n), 4), - the_repository->hash_algo); + p->repo->hash_algo); } else { index += 8; - oidread(oid, index + st_mult(hashsz, n), - the_repository->hash_algo); + oidread(oid, index + st_mult(hashsz, n), p->repo->hash_algo); } return 0; } @@ -1946,7 +1976,7 @@ void check_pack_index_ptr(const struct packed_git *p, const void *vptr) off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n) { const unsigned char *index = p->index_data; - const unsigned int hashsz = the_hash_algo->rawsz; + const unsigned int hashsz = p->repo->hash_algo->rawsz; index += 4 * 256; if (p->index_version == 1) { return ntohl(*((uint32_t *)(index + st_mult(hashsz + 4, n)))); @@ -1963,11 +1993,10 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n) } } -off_t find_pack_entry_one(const unsigned char *sha1, - struct packed_git *p) +off_t find_pack_entry_one(const struct object_id *oid, + struct packed_git *p) { const unsigned char *index = p->index_data; - struct object_id oid; uint32_t result; if (!index) { @@ -1975,8 +2004,7 @@ off_t find_pack_entry_one(const unsigned char *sha1, return 0; } - hashcpy(oid.hash, sha1, the_repository->hash_algo); - if (bsearch_pack(&oid, p, &result)) + if (bsearch_pack(oid, p, &result)) return nth_packed_object_offset(p, result); return 0; } @@ -2002,13 +2030,13 @@ int is_pack_valid(struct packed_git *p) return !open_packed_git(p); } -struct packed_git *find_sha1_pack(const unsigned char *sha1, - struct packed_git *packs) +struct packed_git *find_oid_pack(const struct object_id *oid, + struct packed_git *packs) { struct packed_git *p; for (p = packs; p; p = p->next) { - if (find_pack_entry_one(sha1, p)) + if (find_pack_entry_one(oid, p)) return p; } return NULL; @@ -2025,7 +2053,7 @@ static int fill_pack_entry(const struct object_id *oid, oidset_contains(&p->bad_objects, oid)) return 0; - offset = find_pack_entry_one(oid->hash, p); + offset = find_pack_entry_one(oid, p); if (!offset) return 0; @@ -2128,24 +2156,17 @@ int find_kept_pack_entry(struct repository *r, return 0; } -int has_object_pack(const struct object_id *oid) +int has_object_pack(struct repository *r, const struct object_id *oid) { struct pack_entry e; - return find_pack_entry(the_repository, oid, &e); + return find_pack_entry(r, oid, &e); } -int has_object_kept_pack(const struct object_id *oid, unsigned flags) +int has_object_kept_pack(struct repository *r, const struct object_id *oid, + unsigned flags) { struct pack_entry e; - return find_kept_pack_entry(the_repository, oid, flags, &e); -} - -int has_pack_index(const unsigned char *sha1) -{ - struct stat st; - if (stat(sha1_pack_index_name(sha1), &st)) - return 0; - return 1; + return find_kept_pack_entry(r, oid, flags, &e); } int for_each_object_in_pack(struct packed_git *p, @@ -2156,7 +2177,7 @@ int for_each_object_in_pack(struct packed_git *p, int r = 0; if (flags & FOR_EACH_OBJECT_PACK_ORDER) { - if (load_pack_revindex(the_repository, p)) + if (load_pack_revindex(p->repo, p)) return -1; } @@ -2192,15 +2213,14 @@ int for_each_object_in_pack(struct packed_git *p, return r; } -int for_each_packed_object(each_packed_object_fn cb, void *data, - enum for_each_object_flags flags) +int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, + void *data, enum for_each_object_flags flags) { struct packed_git *p; int r = 0; int pack_errors = 0; - prepare_packed_git(the_repository); - for (p = get_all_packs(the_repository); p; p = p->next) { + for (p = get_all_packs(repo); p; p = p->next) { if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local) continue; if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) && @@ -2224,7 +2244,7 @@ int for_each_packed_object(each_packed_object_fn cb, void *data, } static int add_promisor_object(const struct object_id *oid, - struct packed_git *pack UNUSED, + struct packed_git *pack, uint32_t pos UNUSED, void *set_) { @@ -2232,12 +2252,12 @@ static int add_promisor_object(const struct object_id *oid, struct object *obj; int we_parsed_object; - obj = lookup_object(the_repository, oid); + obj = lookup_object(pack->repo, oid); if (obj && obj->parsed) { we_parsed_object = 0; } else { we_parsed_object = 1; - obj = parse_object(the_repository, oid); + obj = parse_object(pack->repo, oid); } if (!obj) @@ -2278,14 +2298,14 @@ static int add_promisor_object(const struct object_id *oid, return 0; } -int is_promisor_object(const struct object_id *oid) +int is_promisor_object(struct repository *r, const struct object_id *oid) { static struct oidset promisor_objects; static int promisor_objects_prepared; if (!promisor_objects_prepared) { - if (repo_has_promisor_remote(the_repository)) { - for_each_packed_object(add_promisor_object, + if (repo_has_promisor_remote(r)) { + for_each_packed_object(r, add_promisor_object, &promisor_objects, FOR_EACH_OBJECT_PROMISOR_ONLY | FOR_EACH_OBJECT_PACK_ORDER); diff --git a/packfile.h b/packfile.h index eb18ec15db..58104fa009 100644 --- a/packfile.h +++ b/packfile.h @@ -29,21 +29,8 @@ struct pack_entry { * * Example: odb_pack_name(out, sha1, "idx") => ".git/objects/pack/pack-1234..idx" */ -char *odb_pack_name(struct strbuf *buf, const unsigned char *sha1, const char *ext); - -/* - * Return the name of the (local) packfile with the specified sha1 in - * its name. The return value is a pointer to memory that is - * overwritten each time this function is called. - */ -char *sha1_pack_name(const unsigned char *sha1); - -/* - * Return the name of the (local) pack index file with the specified - * sha1 in its name. The return value is a pointer to memory that is - * overwritten each time this function is called. - */ -char *sha1_pack_index_name(const unsigned char *sha1); +char *odb_pack_name(struct repository *r, struct strbuf *buf, + const unsigned char *hash, const char *ext); /* * Return the basename of the packfile, omitting any containing directory @@ -51,10 +38,24 @@ char *sha1_pack_index_name(const unsigned char *sha1); */ const char *pack_basename(struct packed_git *p); -struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); +/* + * Parse the pack idx file found at idx_path and create a packed_git struct + * which can be used with find_pack_entry_one(). + * + * You probably don't want to use this function! It skips most of the normal + * sanity checks (including whether we even have the matching .pack file), + * and does not add the resulting packed_git struct to the internal list of + * packs. You probably want add_packed_git() instead. + */ +struct packed_git *parse_pack_index(struct repository *r, unsigned char *sha1, + const char *idx_path); typedef void each_file_in_pack_dir_fn(const char *full_path, size_t full_path_len, const char *file_name, void *data); +void for_each_file_in_pack_subdir(const char *objdir, + const char *subdir, + each_file_in_pack_dir_fn fn, + void *data); void for_each_file_in_pack_dir(const char *objdir, each_file_in_pack_dir_fn fn, void *data); @@ -80,10 +81,15 @@ struct packed_git *get_all_packs(struct repository *r); */ unsigned long repo_approximate_object_count(struct repository *r); -struct packed_git *find_sha1_pack(const unsigned char *sha1, - struct packed_git *packs); +/* + * Find the pack within the "packs" list whose index contains the object "oid". + * For general object lookups, you probably don't want this; use + * find_pack_entry() instead. + */ +struct packed_git *find_oid_pack(const struct object_id *oid, + struct packed_git *packs); -void pack_report(void); +void pack_report(struct repository *repo); /* * mmap the index file for the specified packfile (if it is not @@ -109,7 +115,8 @@ void close_pack(struct packed_git *); void close_object_store(struct raw_object_store *o); void unuse_pack(struct pack_window **); void clear_delta_base_cache(void); -struct packed_git *add_packed_git(const char *path, size_t path_len, int local); +struct packed_git *add_packed_git(struct repository *r, const char *path, + size_t path_len, int local); /* * Unlink the .pack and associated extension files. @@ -150,10 +157,10 @@ int nth_packed_object_id(struct object_id *, struct packed_git *, uint32_t n); off_t nth_packed_object_offset(const struct packed_git *, uint32_t n); /* - * If the object named sha1 is present in the specified packfile, + * If the object named by oid is present in the specified packfile, * return its offset within the packfile; otherwise, return 0. */ -off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *); +off_t find_pack_entry_one(const struct object_id *oid, struct packed_git *); int is_pack_valid(struct packed_git *); void *unpack_entry(struct repository *r, struct packed_git *, off_t, enum object_type *, unsigned long *); @@ -186,16 +193,15 @@ const struct packed_git *has_packed_and_bad(struct repository *, const struct ob int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e); int find_kept_pack_entry(struct repository *r, const struct object_id *oid, unsigned flags, struct pack_entry *e); -int has_object_pack(const struct object_id *oid); -int has_object_kept_pack(const struct object_id *oid, unsigned flags); - -int has_pack_index(const unsigned char *sha1); +int has_object_pack(struct repository *r, const struct object_id *oid); +int has_object_kept_pack(struct repository *r, const struct object_id *oid, + unsigned flags); /* * Return 1 if an object in a promisor packfile is or refers to the given * object, 0 otherwise. */ -int is_promisor_object(const struct object_id *oid); +int is_promisor_object(struct repository *r, const struct object_id *oid); /* * Expose a function for fuzz testing. @@ -205,7 +211,7 @@ int is_promisor_object(const struct object_id *oid); * * This function should not be used directly. It is exposed here only so that we * have a convenient entry-point for fuzz testing. For real uses, you should - * probably use open_pack_index() or parse_pack_index() instead. + * probably use open_pack_index() instead. */ int load_idx(const char *path, const unsigned int hashsz, void *idx_map, size_t idx_size, struct packed_git *p); @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "editor.h" @@ -14,6 +16,7 @@ int pager_use_color = 1; static struct child_process pager_process; static char *pager_program; +static int old_fd1 = -1, old_fd2 = -1; /* Is the value coming back from term_columns() just a guess? */ static int term_columns_guessed; @@ -23,10 +26,11 @@ static void close_pager_fds(void) { /* signal EOF to pager */ close(1); - close(2); + if (old_fd2 != -1) + close(2); } -static void wait_for_pager_atexit(void) +static void finish_pager(void) { fflush(stdout); fflush(stderr); @@ -34,8 +38,37 @@ static void wait_for_pager_atexit(void) finish_command(&pager_process); } +static void wait_for_pager_atexit(void) +{ + if (old_fd1 == -1) + return; + + finish_pager(); +} + +void wait_for_pager(void) +{ + if (old_fd1 == -1) + return; + + finish_pager(); + sigchain_pop_common(); + unsetenv("GIT_PAGER_IN_USE"); + dup2(old_fd1, 1); + close(old_fd1); + old_fd1 = -1; + if (old_fd2 != -1) { + dup2(old_fd2, 2); + close(old_fd2); + old_fd2 = -1; + } +} + static void wait_for_pager_signal(int signo) { + if (old_fd1 == -1) + return; + close_pager_fds(); finish_command_in_signal(&pager_process); sigchain_pop(signo); @@ -61,7 +94,8 @@ const char *git_pager(int stdout_is_tty) pager = getenv("GIT_PAGER"); if (!pager) { if (!pager_program) - read_early_config(core_pager_config, NULL); + read_early_config(the_repository, + core_pager_config, NULL); pager = pager_program; } if (!pager) @@ -111,6 +145,7 @@ void prepare_pager_args(struct child_process *pager_process, const char *pager) void setup_pager(void) { + static int once = 0; const char *pager = git_pager(isatty(1)); if (!pager) @@ -140,14 +175,20 @@ void setup_pager(void) die("unable to execute pager '%s'", pager); /* original process continues, but writes to the pipe */ + old_fd1 = dup(1); dup2(pager_process.in, 1); - if (isatty(2)) + if (isatty(2)) { + old_fd2 = dup(2); dup2(pager_process.in, 2); + } close(pager_process.in); - /* this makes sure that the parent terminates after the pager */ sigchain_push_common(wait_for_pager_signal); - atexit(wait_for_pager_atexit); + + if (!once) { + once++; + atexit(wait_for_pager_atexit); + } } int pager_in_use(void) @@ -196,6 +237,8 @@ int term_columns(void) */ void term_clear_line(void) { + if (!isatty(2)) + return; if (is_terminal_dumb()) /* * Fall back to print a terminal width worth of space @@ -258,7 +301,7 @@ int check_pager_config(const char *cmd) data.want = -1; data.value = NULL; - read_early_config(pager_command_config, &data); + read_early_config(the_repository, pager_command_config, &data); if (data.value) pager_program = data.value; @@ -5,6 +5,7 @@ struct child_process; const char *git_pager(int stdout_is_tty); void setup_pager(void); +void wait_for_pager(void); int pager_in_use(void); int term_columns(void); void term_clear_line(void); diff --git a/parallel-checkout.c b/parallel-checkout.c index 08b960aac8..01736f1352 100644 --- a/parallel-checkout.c +++ b/parallel-checkout.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "entry.h" diff --git a/parse-options.c b/parse-options.c index 30b9e68f8a..33bfba0ed4 100644 --- a/parse-options.c +++ b/parse-options.c @@ -60,12 +60,12 @@ static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p, return 0; } -static void fix_filename(const char *prefix, char **file) +static char *fix_filename(const char *prefix, const char *file) { if (!file || !*file) - ; /* leave as NULL */ + return NULL; else - *file = prefix_filename_except_for_dash(prefix, *file); + return prefix_filename_except_for_dash(prefix, file); } static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p, @@ -129,18 +129,24 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p, return 0; case OPTION_FILENAME: + { + const char *value; + + FREE_AND_NULL(*(char **)opt->value); + err = 0; + if (unset) - *(const char **)opt->value = NULL; + value = NULL; else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) - *(const char **)opt->value = (const char *)opt->defval; + value = (const char *) opt->defval; else - err = get_arg(p, opt, flags, (const char **)opt->value); + err = get_arg(p, opt, flags, &value); if (!err) - fix_filename(p->prefix, (char **)opt->value); + *(char **)opt->value = fix_filename(p->prefix, value); return err; - + } case OPTION_CALLBACK: { const char *p_arg = NULL; diff --git a/parse-options.h b/parse-options.h index ae15342390..f0801d4532 100644 --- a/parse-options.h +++ b/parse-options.h @@ -3,6 +3,8 @@ #include "gettext.h" +struct repository; + /** * Refer to Documentation/technical/api-parse-options.txt for the API doc. */ @@ -73,7 +75,7 @@ typedef enum parse_opt_result parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, const char *arg, int unset); typedef int parse_opt_subcommand_fn(int argc, const char **argv, - const char *prefix); + const char *prefix, struct repository *repo); /* * `type`:: @@ -30,7 +30,7 @@ static int get_st_mode_bits(const char *path, int *mode) return 0; } -static struct strbuf *get_pathname(void) +struct strbuf *get_pathname(void) { static struct strbuf pathname_array[4] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT @@ -365,15 +365,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len, strbuf_addstr(buf, LOCK_SUFFIX); } -void report_linked_checkout_garbage(void) +void report_linked_checkout_garbage(struct repository *r) { struct strbuf sb = STRBUF_INIT; const struct common_dir *p; int len; - if (!the_repository->different_commondir) + if (!r->different_commondir) return; - strbuf_addf(&sb, "%s/", get_git_dir()); + strbuf_addf(&sb, "%s/", r->gitdir); len = sb.len; for (p = common_list; p->path; p++) { const char *path = p->path; @@ -417,9 +417,9 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id); } -static void do_git_path(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args) +void repo_git_pathv(const 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); @@ -438,7 +438,7 @@ char *repo_git_path(const struct repository *repo, struct strbuf path = STRBUF_INIT; va_list args; va_start(args, fmt); - do_git_path(repo, NULL, &path, fmt, args); + repo_git_pathv(repo, NULL, &path, fmt, args); va_end(args); return strbuf_detach(&path, NULL); } @@ -449,48 +449,10 @@ void strbuf_repo_git_path(struct strbuf *sb, { va_list args; va_start(args, fmt); - do_git_path(repo, NULL, sb, fmt, args); + repo_git_pathv(repo, NULL, sb, fmt, args); va_end(args); } -char *git_path_buf(struct strbuf *buf, const char *fmt, ...) -{ - va_list args; - strbuf_reset(buf); - va_start(args, fmt); - do_git_path(the_repository, NULL, buf, fmt, args); - va_end(args); - return buf->buf; -} - -void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - do_git_path(the_repository, NULL, sb, fmt, args); - va_end(args); -} - -const char *git_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - do_git_path(the_repository, NULL, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - -char *git_pathdup(const char *fmt, ...) -{ - struct strbuf path = STRBUF_INIT; - va_list args; - va_start(args, fmt); - do_git_path(the_repository, NULL, &path, fmt, args); - va_end(args); - return strbuf_detach(&path, NULL); -} - char *mkpathdup(const char *fmt, ...) { struct strbuf sb = STRBUF_INIT; @@ -512,12 +474,17 @@ const char *mkpath(const char *fmt, ...) return cleanup_path(pathname->buf); } -const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) +const char *worktree_git_path(struct repository *r, + const struct worktree *wt, const char *fmt, ...) { struct strbuf *pathname = get_pathname(); va_list args; + + if (wt && wt->repo != r) + BUG("worktree not connected to expected repository"); + va_start(args, fmt); - do_git_path(the_repository, wt, pathname, fmt, args); + repo_git_pathv(r, wt, pathname, fmt, args); va_end(args); return pathname->buf; } @@ -617,26 +584,16 @@ int strbuf_git_path_submodule(struct strbuf *buf, const char *path, return err; } -static void do_git_common_path(const struct repository *repo, - struct strbuf *buf, - const char *fmt, - va_list args) +void repo_common_pathv(const struct repository *repo, + struct strbuf *sb, + const char *fmt, + va_list args) { - strbuf_addstr(buf, repo->commondir); - if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) - strbuf_addch(buf, '/'); - strbuf_vaddf(buf, fmt, args); - strbuf_cleanup_path(buf); -} - -const char *git_common_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - do_git_common_path(the_repository, pathname, fmt, args); - va_end(args); - return pathname->buf; + strbuf_addstr(sb, repo->commondir); + if (sb->len && !is_dir_sep(sb->buf[sb->len - 1])) + strbuf_addch(sb, '/'); + strbuf_vaddf(sb, fmt, args); + strbuf_cleanup_path(sb); } void strbuf_git_common_path(struct strbuf *sb, @@ -645,7 +602,7 @@ void strbuf_git_common_path(struct strbuf *sb, { va_list args; va_start(args, fmt); - do_git_common_path(repo, sb, fmt, args); + repo_common_pathv(repo, sb, fmt, args); va_end(args); } @@ -727,7 +684,7 @@ return_null: * links. User relative paths are also returned as they are given, * except DWIM suffixing. */ -const char *enter_repo(const char *path, int strict) +const char *enter_repo(const char *path, unsigned flags) { static struct strbuf validated_path = STRBUF_INIT; static struct strbuf used_path = STRBUF_INIT; @@ -735,7 +692,7 @@ const char *enter_repo(const char *path, int strict) if (!path) return NULL; - if (!strict) { + if (!(flags & ENTER_REPO_STRICT)) { static const char *suffix[] = { "/.git", "", ".git/.git", ".git", NULL, }; @@ -779,7 +736,8 @@ const char *enter_repo(const char *path, int strict) if (!suffix[i]) return NULL; gitfile = read_gitfile(used_path.buf); - die_upon_dubious_ownership(gitfile, NULL, used_path.buf); + if (!(flags & ENTER_REPO_ANY_OWNER_OK)) + die_upon_dubious_ownership(gitfile, NULL, used_path.buf); if (gitfile) { strbuf_reset(&used_path); strbuf_addstr(&used_path, gitfile); @@ -790,7 +748,8 @@ const char *enter_repo(const char *path, int strict) } else { const char *gitfile = read_gitfile(path); - die_upon_dubious_ownership(gitfile, NULL, path); + if (!(flags & ENTER_REPO_ANY_OWNER_OK)) + die_upon_dubious_ownership(gitfile, NULL, path); if (gitfile) path = gitfile; if (chdir(path)) @@ -25,7 +25,7 @@ char *mkpathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); /* - * The `git_common_path` family of functions will construct a path into a + * The `strbuf_git_common_path` family of functions will construct a path into a * repository's common git directory, which is shared by all worktrees. */ @@ -37,17 +37,13 @@ void strbuf_git_common_path(struct strbuf *sb, const struct repository *repo, 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); /* - * Return a statically allocated path into the main repository's - * (the_repository) common git directory. - */ -const char *git_common_path(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); - - -/* - * The `git_path` family of functions will construct a path into a repository's + * The `repo_git_path` family of functions will construct a path into a repository's * git directory. * * These functions will perform adjustments to the resultant path to account @@ -67,6 +63,14 @@ char *repo_git_path(const struct repository *repo, __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`. */ @@ -76,40 +80,14 @@ void strbuf_repo_git_path(struct strbuf *sb, __attribute__((format (printf, 3, 4))); /* - * Return a statically allocated path into the main repository's - * (the_repository) git directory. - */ -const char *git_path(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); - -/* - * Similar to git_path() but can produce paths for a specified - * worktree instead of current one + * Similar to repo_git_path() but can produce paths for a specified + * worktree instead of current one. When no worktree is given, then the path is + * computed relative to main worktree of the given repository. */ -const char *worktree_git_path(const struct worktree *wt, +const char *worktree_git_path(struct repository *r, + const struct worktree *wt, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); - -/* - * Return a path into the main repository's (the_repository) git directory. - */ -char *git_pathdup(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); - -/* - * 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. - */ -char *git_path_buf(struct strbuf *buf, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into the main repository's (the_repository) git directory - * and append it to the provided buffer `sb`. - */ -void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); + __attribute__((format (printf, 3, 4))); /* * Return a path into the worktree of repository `repo`. @@ -147,24 +125,15 @@ int strbuf_git_path_submodule(struct strbuf *sb, const char *path, const char *fmt, ...) __attribute__((format (printf, 3, 4))); -void report_linked_checkout_garbage(void); +void report_linked_checkout_garbage(struct repository *r); /* * You can define a static memoized git path like: * - * static GIT_PATH_FUNC(git_path_foo, "FOO") + * static REPO_GIT_PATH_FUNC(git_path_foo, "FOO") * * or use one of the global ones below. */ -#define GIT_PATH_FUNC(func, filename) \ - const char *func(void) \ - { \ - static char *ret; \ - if (!ret) \ - ret = git_pathdup(filename); \ - return ret; \ - } - #define REPO_GIT_PATH_FUNC(var, filename) \ const char *git_path_##var(struct repository *r) \ { \ @@ -187,7 +156,22 @@ int calc_shared_perm(int mode); int adjust_shared_perm(const char *path); char *interpolate_path(const char *path, int real_home); -const char *enter_repo(const char *path, int strict); + +/* The bits are as follows: + * + * - ENTER_REPO_STRICT: callers that require exact paths (as opposed + * to allowing known suffixes like ".git", ".git/.git" to be + * omitted) can set this bit. + * + * - ENTER_REPO_ANY_OWNER_OK: callers that are willing to run without + * ownership check can set this bit. + */ +enum { + ENTER_REPO_STRICT = (1<<0), + ENTER_REPO_ANY_OWNER_OK = (1<<1), +}; + +const char *enter_repo(const char *path, unsigned flags); const char *remove_leading_path(const char *in, const char *prefix); const char *relative_path(const char *in, const char *prefix, struct strbuf *sb); int normalize_path_copy_len(char *dst, const char *src, int *prefix_len); @@ -248,4 +232,99 @@ char *xdg_cache_home(const char *filename); */ 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); + +# 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); \ + 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 */ diff --git a/pathspec.c b/pathspec.c index fe1f0f41af..0fc6f84a6e 100644 --- a/pathspec.c +++ b/pathspec.c @@ -495,9 +495,9 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, if (!have_git_dir()) die(_("'%s' is outside the directory tree"), copyfrom); - hint_path = get_git_work_tree(); + hint_path = repo_get_work_tree(the_repository); if (!hint_path) - hint_path = get_git_dir(); + hint_path = repo_get_git_dir(the_repository); die(_("%s: '%s' is outside repository at '%s'"), elt, copyfrom, absolute_path(hint_path)); } diff --git a/perl/Git.pm b/perl/Git.pm index aebfe0c6e0..6f47d653ab 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -7,7 +7,7 @@ Git - Perl interface to the Git version control system package Git; -use 5.008001; +require v5.26; use strict; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); @@ -187,7 +187,7 @@ sub repository { try { # Note that "--is-bare-repository" must come first, as # --git-dir output could contain newlines. - $out = $search->command([qw(rev-parse --is-bare-repository --git-dir)], + $out = $search->command([qw(rev-parse --is-bare-repository --absolute-git-dir)], STDERR => 0); } catch Git::Error::Command with { throw Error::Simple("fatal: not a git repository: $opts{Directory}"); @@ -196,12 +196,12 @@ sub repository { chomp $out; my ($bare, $dir) = split /\n/, $out, 2; - require Cwd; - if ($bare ne 'true') { - require File::Spec; - File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir; - $opts{Repository} = Cwd::abs_path($dir); + # We know this is an absolute path, because we used + # --absolute-git-dir above. + $opts{Repository} = $dir; + if ($bare ne 'true') { + require Cwd; # If --git-dir went ok, this shouldn't die either. my $prefix = $search->command_oneline('rev-parse', '--show-prefix'); $dir = Cwd::abs_path($opts{Directory}) . '/'; @@ -214,8 +214,6 @@ sub repository { $opts{WorkingCopy} = $dir; $opts{WorkingSubdir} = $prefix; - } else { - $opts{Repository} = Cwd::abs_path($dir); } delete $opts{Directory}; diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm index 5454c3a6d2..ab46edb608 100644 --- a/perl/Git/I18N.pm +++ b/perl/Git/I18N.pm @@ -1,5 +1,5 @@ package Git::I18N; -use 5.008001; +require v5.26; use strict; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); BEGIN { @@ -111,7 +111,7 @@ L<Locale::Messages>'s ngettext function or passthrough fallback function. =head2 N__($) No-operation that only returns its argument. Use this if you want xgettext to -extract the text to the pot template but do not want to trigger retrival of the +extract the text to the pot template but do not want to trigger retrieval of the translation at run time. =head1 AUTHOR diff --git a/perl/Git/LoadCPAN.pm b/perl/Git/LoadCPAN.pm index 8c7fa805f9..61254fddbb 100644 --- a/perl/Git/LoadCPAN.pm +++ b/perl/Git/LoadCPAN.pm @@ -1,5 +1,5 @@ package Git::LoadCPAN; -use 5.008001; +require v5.26; use strict; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); diff --git a/perl/Git/Packet.pm b/perl/Git/Packet.pm index d896e69523..00fd9c484a 100644 --- a/perl/Git/Packet.pm +++ b/perl/Git/Packet.pm @@ -1,5 +1,5 @@ package Git::Packet; -use 5.008001; +require v5.26; use strict; use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : (); BEGIN { diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index 7721708ce5..b0913ca1b6 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -763,7 +763,7 @@ sub prop_walk { # this needs to be updated. ++$interesting_props if /^svn:(?:ignore|keywords|executable |eol-style|mime-type - |externals|needs-lock)$/x; + |externals|needs-lock|global-ignores)$/x; } &$sub($self, $p, $props) if $interesting_props; @@ -7,8 +7,8 @@ Leader: Alexander Shopov <ash@kambanaria.org> Language: ca (Catalan) Repository: https://github.com/Softcatala/git-po -Leader: Jordi Mas <jmas@softcatala.org> -Members: Alex Henrie <alexhenrie24@gmail.com> +Leader: Mikel Forcada <mikel.forcada@gmail.com> +Members: Jordi Mas <jmas@softcatala.org> Language: de (German) Repository: https://github.com/ralfth/git @@ -218,9 +218,13 @@ # symref файл Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» (regular file that stores a string that begins with ref: refs/) # human-readable четим от хора # pseudoref пÑевдоуказател, напр. MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD или REBASE_HEAD +# pseudo-merge пÑевдо Ñливанe # reftable таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸ # its referent '%s' ÑÐ¾Ñ‡ÐµÑ‰Ð¸Ñ Ð³Ð¾ „%s“ -# +# dry run пробно изпълнение +# mailmap файл за ÑъответÑтвиÑта на имената и адреÑите на е-поща +# unit test поединичен теÑÑ‚ +# test suite група теÑтове # # ------------------------ # „$var“ - може да не Ñработва за shell има gettext и eval_gettext - проверка - намират Ñе леÑно по „$ @@ -249,8 +253,8 @@ msgid "" msgstr "" "Project-Id-Version: git 2.45\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-21 16:59+0200\n" -"PO-Revision-Date: 2024-04-21 17:00+0200\n" +"POT-Creation-Date: 2024-10-05 01:20+0000\n" +"PO-Revision-Date: 2024-10-05 13:20+0200\n" "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" @@ -806,7 +810,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j — без решение за парчето, към Ñледващото парче без решение\n" @@ -818,8 +822,13 @@ msgstr "" "s — разделÑне на текущото парче на по-малки\n" "e — ръчно редактиране на текущото парче\n" "p — извеждане на текущото парче\n" +"P — извеждане на текущото парче през програма за прелиÑтване\n" "? — извеждане на помощта\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Очаква Ñе Ñамо един знак, а не „%s“" + msgid "No previous hunk" msgstr "ÐÑма друго парче преди това" @@ -868,9 +877,19 @@ msgstr "РазделÑне на %d парчета." msgid "Sorry, cannot edit this hunk" msgstr "Това парче не може да Ñе редактира" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Ðепозната команда „%s“ (за помощ натиÑнете „?“)" + msgid "'git apply' failed" msgstr "неуÑпешно изпълнение на „git apply“" +msgid "No changes." +msgstr "ÐÑма промѐни." + +msgid "Only binary files changed." +msgstr "Променени Ñа Ñамо двоични файлове." + #, c-format msgid "" "\n" @@ -1399,10 +1418,6 @@ msgstr[0] "Прилагане на кръпката „%%s“ Ñ %d отхвър msgstr[1] "Прилагане на кръпката „%%s“ Ñ %d отхвърлени парчета…" #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "Ñъкращаване на името на файла Ñ Ð¾Ñ‚Ñ…Ð²ÑŠÑ€Ð»ÐµÐ½Ð¸Ñ‚Ðµ парчета на „%.*s.rej“" - -#, c-format msgid "cannot open %s" msgstr "„%s“ не може да Ñе отвори" @@ -1504,6 +1519,15 @@ msgstr "" "пробване Ñ Ñ‚Ñ€Ð¾Ð¹Ð½Ð¾ Ñливане, ако това не Ñработи — Ñтандартно прилагане на " "кръпка" +msgid "for conflicts, use our version" +msgstr "при конфликти да Ñе ползва локалната верÑиÑ" + +msgid "for conflicts, use their version" +msgstr "при конфликти да Ñе ползва чуждата верÑиÑ" + +msgid "for conflicts, use a union version" +msgstr "при конфликти да Ñе ползва обединена верÑиÑ" + msgid "build a temporary index based on embedded index information" msgstr "" "Ñъздаване на временен Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база на включената Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° индекÑа" @@ -1551,6 +1575,9 @@ msgstr "добавÑне на тази ÐÐЧÐЛÐÐ_ДИРЕКТОРИЯ къРmsgid "don't return error for empty patches" msgstr "да не Ñе връща грешка при празни кръпки" +msgid "--ours, --theirs, and --union require --3way" +msgstr "опциите „--ours“, „--theirs“ и „--union“ изиÑкват опциÑта „--3way“" + #, c-format msgid "cannot stream blob %s" msgstr "обектът-BLOB „%s“ не може да Ñе обработи" @@ -1623,6 +1650,10 @@ msgid "not a tree object: %s" msgstr "не е обект-дърво: %s" #, c-format +msgid "failed to unpack tree object %s" +msgstr "неуÑпешно разпакетиране на обект-дърво „%s“" + +#, c-format msgid "File not found: %s" msgstr "Файлът „%s“ липÑва" @@ -1752,6 +1783,10 @@ msgstr "преÑкачане на прекалено Ð³Ð¾Ð»ÐµÐ¼Ð¸Ñ Ñ„Ð°Ð¹Ð» зРmsgid "ignoring overly large gitattributes blob '%s'" msgstr "преÑкачане на прекалено Ð³Ð¾Ð»ÐµÐ¼Ð¸Ñ Ð¾Ð±ÐµÐºÑ‚-BLOB за атрибути на git: „%s“" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "" +"опциÑта „--attr-source“ и променливата „GIT_ATTR_SOURCE“ изиÑкват хранилище" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "" "неправилна ÑтойноÑÑ‚ за опциÑта „--attr-source“ или променливата " @@ -1834,6 +1869,10 @@ msgid "could not create file '%s'" msgstr "файлът „%s“ не може да Ñе Ñъздаде" #, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "дейÑтвието „show“ не може да Ñе изпълни за обект „%s“" + +#, c-format msgid "could not read file '%s'" msgstr "файлът „%s“ не може да Ñе прочете" @@ -2072,13 +2111,6 @@ msgstr "права̀та на „%2$s“ не може да Ñе зададат msgid "Unstaged changes after refreshing the index:" msgstr "Промѐни, които и Ñлед обновÑването на индекÑа не Ñа добавени към него:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"ÐаÑтройката „add.interactive.useBuiltin“ е премахната!\n" -"За подробноÑти Ñ Ð¿Ð¾Ñ‚ÑŠÑ€Ñете в изхода от „git help config“." - msgid "could not read the index" msgstr "индекÑÑŠÑ‚ не може да Ñе прочете" @@ -2541,6 +2573,9 @@ msgstr "" msgid "show the patch being applied" msgstr "показване на прилаганата кръпка" +msgid "try to apply current patch again" +msgstr "нов опит за прилагане на текущата кръпка" + msgid "record the empty patch as an empty commit" msgstr "прилагане на празна кръпка като празно подаване" @@ -2598,9 +2633,6 @@ msgstr "git apply [ОПЦИЯ…] [КРЪПКÐ…]" msgid "could not redirect output" msgstr "изходът не може да Ñе пренаÑочи" -msgid "git archive: Remote with no URL" -msgstr "git archive: ЛипÑва Ð°Ð´Ñ€ÐµÑ Ð·Ð° отдалеченото хранилище" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "" "git archive: очакваше Ñе „ACK“/„NAK“, а бе получен изчиÑтващ пакет „flush“" @@ -2758,9 +2790,6 @@ msgstr "" "на „git bisect terms“ е подаден неправилен аргумент „%s“\n" "Поддържат Ñе опциите „--term-good“/„--term-old“ и „--term-bad„/„--term-new“." -msgid "revision walk setup failed\n" -msgstr "неуÑпешно наÑтройване на обхождането на верÑиите\n" - #, c-format msgid "could not open '%s' for appending" msgstr "файлът „%s“ не може да Ñе отвори за добавÑне" @@ -3535,6 +3564,9 @@ msgstr "За Ñъздаването на пратка е необходимо Ñ… msgid "do not show bundle details" msgstr "без подробна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° пратките" +msgid "need a repository to verify a bundle" +msgstr "за проверката на пратка е необходимо хранилище" + #, c-format msgid "%s is okay\n" msgstr "Пратката „%s“ е наред\n" @@ -3773,9 +3805,17 @@ msgstr "git check-mailmap [ОПЦИЯ…] КОÐТÐКТ…" msgid "also read contacts from stdin" msgstr "четене на контакти и от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" -#, c-format -msgid "unable to parse contact: %s" -msgstr "контактът не може да бъде анализиран: %s" +msgid "read additional mailmap entries from file" +msgstr "" +"изчитане на допълнителните ÑъответÑÑ‚Ð²Ð¸Ñ Ð½Ð° имена и адреÑи на е-поща от ФÐЙЛ" + +msgid "blob" +msgstr "обект-BLOB" + +msgid "read additional mailmap entries from blob" +msgstr "" +"изчитане на допълнителните ÑъответÑÑ‚Ð²Ð¸Ñ Ð½Ð° имена и адреÑи на е-поща от обект-" +"BLOB" msgid "no contacts specified" msgstr "не Ñа указани контакти" @@ -4130,6 +4170,10 @@ msgid "'%s' cannot be used with switching branches" msgstr "опциÑта „%s“ е неÑъвмеÑтима Ñ Ð¿Ñ€ÐµÐ¼Ð¸Ð½Ð°Ð²Ð°Ð½ÐµÑ‚Ð¾ от един клон към друг" #, c-format +msgid "'%s' needs the paths to check out" +msgstr "„%s“ изиÑква пътища, които да Ñе изтеглÑÑ‚" + +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "опциÑта „%s“ е неÑъвмеÑтима Ñ â€ž%s“" @@ -4411,7 +4455,7 @@ msgstr "изтриване Ñамо на игнорирани файлове" msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"ÐаÑтройката „clean.requireForce“ е зададена, което изиÑква опцииÑта „-f“. " +"ÐаÑтройката „clean.requireForce“ е зададена, което изиÑква опциÑта „-f“. " "ÐÑма да Ñе извърши изчиÑтване" msgid "git clone [<options>] [--] <repo> [<dir>]" @@ -4569,6 +4613,14 @@ 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“ не може да бъде Ñъздадена" @@ -4917,7 +4969,7 @@ msgstr "git commit-tree: не може да Ñе прочете" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4927,11 +4979,11 @@ msgid "" msgstr "" "git commit [-a|--interactive|--patch] [-s] [-v] [-u РЕЖИМ] [--amend]\n" " [--dry-run] [(-c|-C|--squash) ПОДÐÐ’ÐÐЕ |--fixup [(amend|" -"reword):]ПОДÐÐ’ÐÐЕ)]\n" +"reword):]ПОДÐÐ’ÐÐЕ]\n" " [-F ФÐЙЛ|-m СЪОБЩЕÐИЕ] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=ÐВТОР]\n" " [--date=ДÐТÐ] [--cleanup=РЕЖИМ] [--[no-]status]\n" -" [-i|-o] [--pathspec-from-file=ФÐЙЛ> [--pathspec-file-nul]]\n" +" [-i|-o] [--pathspec-from-file=ФÐЙЛ [--pathspec-file-nul]]\n" " [(--trailer ЛЕКСЕМÐ[(=|:)СТОЙÐОСТ])…] [-" "S[ИДЕÐТИФИКÐТОР_ÐÐ_КЛЮЧ]]\n" " [--] [ПЪТ…]" @@ -5438,15 +5490,56 @@ msgstr "" "\n" " git restore --staged :/" -msgid "git config [<options>]" -msgstr "git config [ОПЦИЯ…]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [ОПЦИЯ_ЗÐ_ФÐЙЛ] [ОПЦИЯ_ЗÐ_ИЗВЕЖДÐÐЕ] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "непознат аргумент към „--type“: %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [ОПЦИЯ_ЗÐ_ФÐЙЛ] [ОПЦИЯ_ЗÐ_ИЗВЕЖДÐÐЕ] [--includes] [--all] [--" +"regexp] [--value=СТОЙÐОСТ] [--fixed-value] [--default=СТÐÐДÐРТÐО] ИМЕ" -msgid "only one type at a time" -msgstr "Ñамо по един вид" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [ОПЦИЯ_ЗÐ_ФÐЙЛ] [--type=ВИД] [--all] [--value=СТОЙÐОСТ] [--" +"fixed-value] ИМЕ СТОЙÐОСТ" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [ОПЦИЯ_ЗÐ_ФÐЙЛ] [--all] [--value=СТОЙÐОСТ] [--fixed-value]" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [ОПЦИЯ_ЗÐ_ФÐЙЛ] СТÐРО_ИМЕ ÐОВО_ИМЕ" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [ОПЦИЯ_ЗÐ_ФÐЙЛ] ИМЕ" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [ОПЦИЯ_ЗÐ_ФÐЙЛ]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "" +"git config [ОПЦИЯ_ЗÐ_ФÐЙЛ] --get-colorbool ИМЕ [СТÐÐД_ИЗХОД_ÐÐ_ТЕРМИÐÐЛ]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [ОПЦИЯ_ЗÐ_ФÐЙЛ] [ОПЦИЯ_ЗÐ_ИЗВЕЖДÐÐЕ] [--includes] [--all] [--" +"regexp=РЕГ_ИЗР][--value=СТОЙÐОСТ] [--fixed-value] [--default=СТÐÐДÐРТÐО] ИМЕ" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [ОПЦИЯ_ЗÐ_ФÐЙЛ] [--type=ВИД] [--comment=СЪОБЩЕÐИЕ] [--all] [--" +"value=СТОЙÐОСТ] [--fixed-value] ИМЕ СТОЙÐОСТ" msgid "Config file location" msgstr "МеÑтоположение на ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»" @@ -5473,57 +5566,6 @@ msgid "read config from given blob object" msgstr "" "изчитане на конфигурациÑта от BLOB Ñ Ñ‚Ð¾Ð·Ð¸ ИДЕÐТИФИКÐТОРна Ñъдържанието" -msgid "Action" -msgstr "ДейÑтвие" - -msgid "get value: name [value-pattern]" -msgstr "извеждане на ÑтойноÑÑ‚: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "get all values: key [value-pattern]" -msgstr "извеждане на вÑички ÑтойноÑти: ключ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "" -"извеждане на ÑтойноÑтите за РЕГУЛЯРÐиÑ_ИЗРÐЗ: РЕГУЛЯРЕÐ_ИЗРÐЗ_ЗÐ_ИМЕТО " -"[ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "извеждане на ÑтойноÑтта за ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð°Ð´Ñ€ÐµÑ: Ð ÐЗДЕЛ[.ПРОМЕÐЛИВÐ] ÐДРЕС" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "" -"замÑна на вÑички Ñъвпадащи променливи: ИМЕ СТОЙÐОСТ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "add a new variable: name value" -msgstr "добавÑне на нова променлива: ИМЕ СТОЙÐОСТ" - -msgid "remove a variable: name [value-pattern]" -msgstr "изтриване на променлива: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "remove all matches: name [value-pattern]" -msgstr "изтриване на вÑички Ñъвпадащи: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" - -msgid "rename section: old-name new-name" -msgstr "преименуване на раздел: СТÐРО_ИМЕ ÐОВО_ИМЕ" - -msgid "remove a section: name" -msgstr "изтриване на раздел: ИМЕ" - -msgid "list all" -msgstr "изброÑване на вÑички" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "доÑловно равенÑтво при ÑравнÑване ÑÑŠÑ Ð¨ÐБЛОÐ_ЗÐ_СТОЙÐОСТ" - -msgid "open an editor" -msgstr "отварÑне на редактор" - -msgid "find the color configured: slot [default]" -msgstr "извеждане на Ð·Ð°Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ñ†Ð²ÑÑ‚: номер [Ñтандартно]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "извеждане на Ð·Ð°Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ñ†Ð²ÑÑ‚: номер (ÑтандартниÑÑ‚ изход е терминал)" - msgid "Type" msgstr "Вид" @@ -5551,8 +5593,8 @@ msgstr "СТОЙÐОСТТРе път (до файл или Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ msgid "value is an expiry date" msgstr "ÑтойноÑтта е период на валидноÑÑ‚/запазване" -msgid "Other" -msgstr "Други" +msgid "Display options" +msgstr "Опции за извеждането" msgid "terminate values with NUL byte" msgstr "разделÑне на ÑтойноÑтите Ñ Ð½ÑƒÐ»ÐµÐ²Ð¸Ñ Ð·Ð½Ð°Ðº „NUL“" @@ -5560,9 +5602,6 @@ msgstr "разделÑне на ÑтойноÑтите Ñ Ð½ÑƒÐ»ÐµÐ²Ð¸Ñ Ð·Ð½Ð°Ð msgid "show variable names only" msgstr "извеждане на имената на променливите" -msgid "respect include directives on lookup" -msgstr "при търÑене да Ñе уважат и директивите за включване" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "извеждане на мÑÑтото на задаване на наÑтройката (файл, Ñтандартен вход, " @@ -5573,14 +5612,15 @@ msgstr "" "извеждане на обхвата на наÑтройката „worktree“ (работно дърво), „local“ " "(хранилище), „global“ (потребител), „system“ (ÑиÑтема), „command“ (команда)" -msgid "value" -msgstr "СТОЙÐОСТ" +msgid "show config keys in addition to their values" +msgstr "извеждане на ключовете в наÑтройките заедно ÑÑŠÑ ÑтойноÑтите им" -msgid "with --get, use default value when missing entry" -msgstr "Ñ â€ž--get“ Ñе използва Ñтандартна СТОЙÐОСТ при липÑваща" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "непознат аргумент към „--type“: %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "низ за подаване четим от хора (при нужда отпред Ñе Ð´Ð¾Ð±Ð°Ð²Ñ â€ž#“)" +msgid "only one type at a time" +msgstr "Ñамо по един вид" #, c-format msgid "wrong number of arguments, should be %d" @@ -5657,50 +5697,73 @@ msgstr "" "повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð²Ð¸Ð¶Ñ‚Ðµ раздела „CONFIGURATION FILE“ в\n" "„git help worktree“" -msgid "--get-color and variable type are incoherent" -msgstr "опциÑта „--get-color“ не ÑъответÑтва на вида на променливата" +msgid "Other" +msgstr "Други" -msgid "only one action at a time" -msgstr "Ñамо по едно дейÑтвие" +msgid "respect include directives on lookup" +msgstr "при търÑене да Ñе уважат и директивите за включване" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "" -"опциÑта „--name-only“ е приложима Ñамо към опциите „--list“ и „--get-regexp“" +#, c-format +msgid "unable to read config file '%s'" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде прочетен" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"опциÑта „--show-origin“ е приложима Ñамо към опциите „--get“, „--get-all“, " -"„--get-regexp“ и „--list“" +msgid "error processing config file(s)" +msgstr "грешка при обработката на конфигурационен файл" -msgid "--default is only applicable to --get" -msgstr "опциÑта „--default“ е приложима Ñамо към опциÑта „--get“" +msgid "Filter options" +msgstr "Опции за филтриране" -msgid "--comment is only applicable to add/set/replace operations" +msgid "return all values for multi-valued config options" +msgstr "връщане на вÑички ÑтойноÑти за опциите, поддържащи много ÑтойноÑти" + +msgid "interpret the name as a regular expression" +msgstr "третиране на името като регулÑрен израз" + +msgid "show config with values matching the pattern" +msgstr "извеждане на наÑтройките ÑÑŠÑ ÑтойноÑти напаÑващи на ШÐБЛОÐа" + +msgid "use string equality when comparing values to value pattern" msgstr "" -"опциÑта „--comment“ е ÑъвмеÑтима Ñамо Ñ Ð´ÐµÐ¹ÑтвиÑта „add“ (добавÑне)/„set“ " -"(задаване)/„replace“ (замÑна)" +"ползване на равенÑтво на низ при ÑравнÑване на ÑтойноÑÑ‚ Ñ Ð¨ÐБЛОÐ_ЗÐ_СТОЙÐОСТ" + +msgid "URL" +msgstr "ÐдреÑ" + +msgid "show config matching the given URL" +msgstr "извеждане на наÑтройките напаÑващи на Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑ" + +msgid "value" +msgstr "СТОЙÐОСТ" + +msgid "use default value when missing entry" +msgstr "ползване на Ñтандартна СТОЙÐОСТ при липÑваща" msgid "--fixed-value only applies with 'value-pattern'" -msgstr "опциÑта „--fixed-value“ е приложима Ñамо ÑÑŠÑ Ð¨ÐБЛОÐ_ЗÐ_СТОЙÐОСТ" +msgstr "опциÑта „--fixed-value“ изиÑква ШÐБЛОÐ_ЗÐ_СТОЙÐОСТ" -#, c-format -msgid "unable to read config file '%s'" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде прочетен" +msgid "--default= cannot be used with --all or --url=" +msgstr "опциÑта „--default=“ е неÑъвмеÑтима Ñ â€ž--all“, „--url=“" -msgid "error processing config file(s)" -msgstr "грешка при обработката на конфигурационен файл" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "опциÑта „--url=“ е неÑъвмеÑтима Ñ â€ž--all“, „--regexp“, „--value“" -msgid "editing stdin is not supported" -msgstr "не Ñе поддържа редактиране на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" +msgid "Filter" +msgstr "Филтриране" -msgid "editing blobs is not supported" -msgstr "не Ñе поддържа редактиране на обекти-BLOB" +msgid "replace multi-valued config option with new value" +msgstr "замÑна на наÑтройка, приемаща много ÑтойноÑти, Ñ Ð½Ð¾Ð²Ð° ÑтойноÑÑ‚" -#, c-format -msgid "cannot create configuration file %s" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде Ñъздаден" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "низ за подаване четим от хора (при нужда отпред Ñе Ð´Ð¾Ð±Ð°Ð²Ñ â€ž#“)" + +msgid "add a new line without altering any existing values" +msgstr "добавÑне на нов ред без промÑна на ÑъщеÑтвуващи ÑтойноÑти" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "опциÑта „--fixed-value“ изиÑква опциÑта „--value=ШÐБЛОÐ_ЗÐ_СТОЙÐОСТ“" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "опциитe „--append“ и „--value=ШÐБЛОÐ_ЗÐ_СТОЙÐОСТ“ Ñа неÑъвмеÑтими" #, c-format msgid "" @@ -5715,6 +5778,92 @@ msgstr "" msgid "no such section: %s" msgstr "такъв раззел нÑма: %s" +msgid "editing stdin is not supported" +msgstr "не Ñе поддържа редактиране на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" + +msgid "editing blobs is not supported" +msgstr "не Ñе поддържа редактиране на обекти-BLOB" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде Ñъздаден" + +msgid "Action" +msgstr "ДейÑтвие" + +msgid "get value: name [<value-pattern>]" +msgstr "извеждане на ÑтойноÑÑ‚: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "get all values: key [<value-pattern>]" +msgstr "извеждане на вÑички ÑтойноÑти: ключ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "" +"извеждане на ÑтойноÑтите за РЕГУЛЯРÐиÑ_ИЗРÐЗ: name-regex " +"[ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "извеждане на ÑтойноÑтта за ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð°Ð´Ñ€ÐµÑ: Ð ÐЗДЕЛ[.ПРОМЕÐЛИВÐ] ÐДРЕС" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "" +"замÑна на вÑички Ñъвпадащи променливи: ИМЕ СТОЙÐОСТ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "add a new variable: name value" +msgstr "добавÑне на нова променлива: ИМЕ СТОЙÐОСТ" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "изтриване на променлива: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "изтриване на вÑички Ñъвпадащи: ИМЕ [ШÐБЛОÐ_ЗÐ_СТОЙÐОСТТÐ]" + +msgid "rename section: old-name new-name" +msgstr "преименуване на раздел: СТÐРО_ИМЕ ÐОВО_ИМЕ" + +msgid "remove a section: name" +msgstr "изтриване на раздел: ИМЕ" + +msgid "list all" +msgstr "изброÑване на вÑички" + +msgid "open an editor" +msgstr "отварÑне на редактор" + +msgid "find the color configured: slot [<default>]" +msgstr "намиране на Ð·Ð°Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ñ†Ð²ÑÑ‚: номер [СТÐÐДÐРТÐО]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "извеждане на Ð·Ð°Ð´Ð°Ð´ÐµÐ½Ð¸Ñ Ñ†Ð²ÑÑ‚: номер (СТÐÐД_ИЗХОД_ÐÐ_ТЕРМИÐÐЛ)" + +msgid "with --get, use default value when missing entry" +msgstr "Ñ â€ž--get“ Ñе използва Ñтандартна СТОЙÐОСТ при липÑваща" + +msgid "--get-color and variable type are incoherent" +msgstr "опциÑта „--get-color“ не ÑъответÑтва на вида на променливата" + +msgid "no action specified" +msgstr "не е зададено дейÑтвие" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "" +"опциÑта „--name-only“ е приложима Ñамо към опциите „--list“ и „--get-regexp“" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"опциÑта „--show-origin“ е приложима Ñамо към опциите „--get“, „--get-all“, " +"„--get-regexp“ и „--list“" + +msgid "--default is only applicable to --get" +msgstr "опциÑта „--default“ е приложима Ñамо към опциÑта „--get“" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "" +"опциÑта „--comment“ е ÑъвмеÑтима Ñамо Ñ Ð´ÐµÐ¹ÑтвиÑта „add“ (добавÑне)/„set“ " +"(задаване)/„replace“ (замÑна)" + msgid "print sizes in human readable format" msgstr "извеждане на размерите на обектите във формат четим от хора" @@ -6214,8 +6363,8 @@ msgstr "" " git config fetch.showForcedUpdates false\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "хранилището „%s“ не изпрати вÑички необходими обекти\n" +msgid "%s did not send all necessary objects" +msgstr "хранилището „%s“ не изпрати вÑички необходими обекти" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -6254,8 +6403,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "ÑтойноÑтта „%2$s“ за опциÑта „%1$s“ не е ÑъвмеÑтима Ñ â€ž%3$s“" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "опциÑта „%s“ Ñе преÑкача при „%s“\n" +msgid "option \"%s\" is ignored for %s" +msgstr "опциÑта „%s“ Ñе преÑкача при „%s“" #, c-format msgid "%s is not a valid object" @@ -6545,7 +6694,7 @@ msgid "read reference patterns from stdin" msgstr "изчитане на шаблоните за указатели от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" msgid "also include HEAD ref and pseudorefs" -msgstr "включване и на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ както и пÑевдоуказателите" +msgstr "включване и на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ както и пÑевдо указателите" msgid "unknown arguments supplied with --stdin" msgstr "непознат аргумент към опциÑта „--stdin“" @@ -6559,12 +6708,16 @@ msgstr "наÑтройка" msgid "config key storing a list of repository paths" msgstr "наÑтройка, коÑто Ñъдържа ÑпиÑък Ñ Ð¿ÑŠÑ‚Ð¸Ñ‰Ð° към хранилища" +msgid "keep going even if command fails in a repository" +msgstr "" +"продължаване на дейÑтвието дори и командата да е неуÑпешна в нÑкое хранилище" + msgid "missing --config=<config>" msgstr "липÑва --config=ÐÐСТРОЙКÐ" #, c-format msgid "got bad config --config=%s" -msgstr "получена е неправилена наÑтройка „--config=%s“" +msgstr "получена е неправилна наÑтройка „--config=%s“" msgid "unknown" msgstr "непознат" @@ -6931,6 +7084,9 @@ msgstr "изчерпателно търÑене на боклука (за Ñме msgid "enable auto-gc mode" msgstr "включване на автоматичното Ñъбиране на боклука (auto-gc)" +msgid "perform garbage collection in the background" +msgstr "Ñъбиране на боклука във фонов режим" + msgid "force running gc even if there may be another gc running" msgstr "" "изрично Ñтартиране на Ñъбирането на боклука, дори и ако вече работи друго " @@ -7035,6 +7191,9 @@ msgstr "задачата „%s“ не може да Ñе избере Ð¿Ð¾Ð²ÐµÑ msgid "run tasks based on the state of the repository" msgstr "изпълнÑване на задачи Ñпоред ÑÑŠÑтоÑнието на хранилището" +msgid "perform maintenance in the background" +msgstr "извършване на дейноÑтите по поддръжка на заден фон" + msgid "frequency" msgstr "чеÑтота" @@ -7914,9 +8073,6 @@ msgstr "опциÑта „-LДИÐПÐЗОÐ:ФÐЙЛ“ не може да Ñе msgid "Final output: %d %s\n" msgstr "Резултат: %d %s\n" -msgid "unable to create temporary object directory" -msgstr "не може да бъде Ñъздадена Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° временни обекти" - #, c-format msgid "git show %s: bad file" msgstr "git show %s: повреден файл" @@ -8041,8 +8197,11 @@ msgstr "отбелÑзване, че това е N-тата поредна реРmsgid "max length of output filename" msgstr "макÑимална дължина на име на вÑеки пакетен файл" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "използване на „[RFC PATCH]“ вмеÑто „[PATCH]“" +msgid "rfc" +msgstr "ПРЕФИКС" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "добавÑне на този ПРЕФИКС (Ñтандартно е „RFC“) пред „PATCH“" msgid "cover-from-description-mode" msgstr "режим-придружаващо-пиÑмо-по-опиÑание" @@ -8282,7 +8441,7 @@ msgid "show resolve-undo information" msgstr "извеждане на информациÑта за отмÑна на разрешените подаваниÑ" msgid "skip files matching pattern" -msgstr "преÑкачане на файловете напаÑващи ШÐБЛОÐа" +msgstr "преÑкачане на файловете напаÑващи на ШÐБЛОÐа" msgid "read exclude patterns from <file>" msgstr "изчитане на шаблоните за игнориране от ФÐЙЛ" @@ -8325,13 +8484,13 @@ msgstr "" "deduplicate“/„--eol“" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=КОМÐÐДÐ]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=КОМÐÐДÐ]\n" " [-q|--quiet] [--exit-code] [--get-url] [--sort=КЛЮЧ]\n" -" [--symref] [ХРÐÐИЛИЩЕ [ШÐБЛОÐ]]" +" [--symref] [ХРÐÐИЛИЩЕ [ШÐБЛОÐ…]]" msgid "do not print remote URL" msgstr "без извеждане на адреÑите на отдалечените хранилища" @@ -8345,8 +8504,11 @@ msgstr "път към командата „git-upload-pack“ на отдале msgid "limit to tags" msgstr "Ñамо етикетите" -msgid "limit to heads" -msgstr "Ñамо върховете" +msgid "limit to branches" +msgstr "Ñамо клоните" + +msgid "deprecated synonym for --branches" +msgstr "оÑтарÑл Ñиноним на „--branches“" msgid "do not show peeled tags" msgstr "без проÑледÑване на непреките етикети" @@ -8501,15 +8663,6 @@ msgstr "Ñливане на базата на „diff3“" msgid "use a zealous diff3 based merge" msgstr "заÑилено Ñливане на базата на „diff3“" -msgid "for conflicts, use our version" -msgstr "при конфликти да Ñе ползва локалната верÑиÑ" - -msgid "for conflicts, use their version" -msgstr "при конфликти да Ñе ползва чуждата верÑиÑ" - -msgid "for conflicts, use a union version" -msgstr "при конфликти да Ñе ползва обединена верÑиÑ" - msgid "<algorithm>" msgstr "ÐЛГОРИТЪМ" @@ -8989,6 +9142,9 @@ msgstr "" msgid "write multi-pack bitmap" msgstr "запазване на многопакетната битова маÑка" +msgid "write a new incremental MIDX" +msgstr "запазване на нов файл Ñ Ð½Ð°Ñ€Ð°Ñтващ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети" + msgid "write multi-pack index containing only given indexes" msgstr "" "запазване на битовата маÑка за множеÑтво пакети, Ñъдържаща Ñамо дадените " @@ -9206,10 +9362,6 @@ msgstr "git notes prune [ОПЦИЯ…]" msgid "Write/edit the notes for the following object:" msgstr "ЗапиÑване/редактиране на бележките за ÑÐ»ÐµÐ´Ð½Ð¸Ñ Ð¾Ð±ÐµÐºÑ‚:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "дейÑтвието „show“ не може да Ñе изпълни за обект „%s“" - msgid "could not read 'show' output" msgstr "изведената Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ дейÑтвието „show“ не може да Ñе прочете" @@ -11076,6 +11228,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +msgstr "указване на форма̀та за указател, към който да Ñе конвертира" + +msgid "perform a non-destructive dry-run" +msgstr "пробно изпълнение — без промÑна на данни" + +msgid "missing --ref-format=<format>" +msgstr "липÑва опциÑта --ref-format=ФОРМÐТ" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "хранилището вече ползва форма̀та „%s“" + +msgid "enable strict checking" +msgstr "Ñтроги проверки" + +msgid "'git refs verify' takes no arguments" +msgstr "командата „git refs verify“ не приема аргументи" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -11363,9 +11540,6 @@ msgstr "◠отдалечено хранилище „%s“" msgid " Fetch URL: %s" msgstr " ÐÐ´Ñ€ÐµÑ Ð·Ð° доÑтавÑне: %s" -msgid "(no URL)" -msgstr "(без адреÑ)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -11374,6 +11548,9 @@ msgstr "(без адреÑ)" msgid " Push URL: %s" msgstr " ÐÐ´Ñ€ÐµÑ Ð·Ð° изтлаÑкване: %s" +msgid "(no URL)" +msgstr "(без адреÑ)" + #, c-format msgid " HEAD branch: %s" msgstr " клон Ñочен от HEAD: %s" @@ -11483,10 +11660,6 @@ msgstr "запитване към адреÑите за изтлаÑкване, msgid "return all URLs" msgstr "извеждане на вÑички адреÑи" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "не е зададен Ð°Ð´Ñ€ÐµÑ Ð·Ð° отдалеченото хранилище „%s“" - msgid "manipulate push URLs" msgstr "промÑна на адреÑите за изтлаÑкване" @@ -12511,12 +12684,12 @@ msgstr "Ðепознат алгоритъм за контролни Ñуми" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d|--dereference]\n" -" [-s|--hash[=БРОЙ]] [--abbrev[=БРОЙ]] [--tags]\n" -" [--heads] [--] [ШÐБЛОÐ…]" +" [-s|--hash[=БРОЙ]] [--abbrev[=БРОЙ]] [--branches] [--tags]\n" +" [--] [ШÐБЛОÐ…]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -12539,11 +12712,11 @@ msgstr "указателÑÑ‚ не ÑъщеÑтвува" msgid "failed to look up reference" msgstr "Ñоченото от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð»Ð¸Ð¿Ñва" -msgid "only show tags (can be combined with heads)" -msgstr "извеждане на етикетите (може да Ñе комбинира Ñ Ð²ÑŠÑ€Ñ…Ð¾Ð²ÐµÑ‚Ðµ)" +msgid "only show tags (can be combined with --branches)" +msgstr "извеждане на етикетите (може да Ñе комбинира Ñ â€ž--branches“ за клони)" -msgid "only show heads (can be combined with tags)" -msgstr "извеждане на върховете (може да Ñе комбинира Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚Ð¸Ñ‚Ðµ)" +msgid "only show branches (can be combined with --tags)" +msgstr "извеждане на клоните (може да Ñе комбинира Ñ â€ž--tags“ за етикети)" msgid "check for reference existence without resolving" msgstr "проверка за ÑъщеÑтвуване на указател без проÑледÑването му" @@ -12598,6 +12771,10 @@ msgstr "директориÑта „%s“ не може да бъде изтри msgid "failed to create directory for sparse-checkout file" msgstr "директориÑта за чаÑтично изтеглÑне „%s“ не може да бъде Ñъздадена" +#, c-format +msgid "unable to fdopen %s" +msgstr "обектът „%s“ не може да бъде отворен Ñ â€žfdopen“" + msgid "failed to initialize worktree config" msgstr "наÑтройките на работното дърво не може да Ñе инициализират" @@ -13056,8 +13233,8 @@ msgid "couldn't hash object from '%s'" msgstr "неуÑпешно изчиÑлÑване на контролната Ñума на обект от „%s“" #, c-format -msgid "unexpected mode %o\n" -msgstr "неочакван режим „%o“\n" +msgid "unexpected mode %o" +msgstr "неочакван режим „%o“" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "" @@ -13183,14 +13360,14 @@ msgstr "" "друг подмодул" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "ÐеуÑпешно клониране на адреÑа „%s“ в Ð¿ÑŠÑ‚Ñ â€ž%s“ като подмодул" - -#, c-format msgid "directory not empty: '%s'" msgstr "директориÑта не е празна: „%s“" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "ÐеуÑпешно клониране на адреÑа „%s“ в Ð¿ÑŠÑ‚Ñ â€ž%s“ като подмодул" + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "директориÑта на подмодула „%s“ не може да бъде получена" @@ -13555,9 +13732,11 @@ msgstr "причина за обновÑването" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a|-s|-u ИДЕÐТИФИКÐТОР_ÐÐ_КЛЮЧ] [-f] [-m СЪОБЩЕÐИЕ|-F ФÐЙЛ] [-e]\n" +" [(--trailer ЛЕКСЕМÐ[(=|:)СТОЙÐОСТ])…]\n" " ЕТИКЕТ [ПОДÐÐ’ÐÐЕ|ОБЕКТ]" msgid "git tag -d <tagname>..." @@ -14443,9 +14622,6 @@ msgstr "непозната заглавна чаÑÑ‚: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Ð’ хранилището липÑват Ñледните необходими подаваниÑ:" -msgid "need a repository to verify a bundle" -msgstr "за проверката на пратка е необходимо хранилище" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14856,6 +15032,9 @@ msgstr "Получаване на изтлаÑканото в хранилище msgid "Manage reflog information" msgstr "Управление на информациÑта в журнала на указателите" +msgid "Low-level access to refs" +msgstr "ДоÑтъп от ниÑко ниво до указателите" + msgid "Manage set of tracked repositories" msgstr "Управление на набор от Ñледени хранилища" @@ -15167,6 +15346,14 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "" "откъÑÑŠÑ‚ за данните необходими на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта липÑва или е повреден" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"изключване на филтрите на Блум за Ñлой „%s“ на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта поради " +"неÑъвмеÑтими наÑтройки" + msgid "commit-graph has no base graphs chunk" msgstr "базовиÑÑ‚ Ð¾Ñ‚ÐºÑŠÑ Ð»Ð¸Ð¿Ñва в гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта" @@ -15298,6 +15485,14 @@ msgstr "" "опит за Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта, но наÑтройката „core.commitGraph“ е " "изключена" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"опит за Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта, но наÑтройката „commitGraph." +"changedPathsVersion“ (%d) не Ñе поддържа" + msgid "too many commits to write graph" msgstr "прекалено много Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð° запиÑване на гра̀фа" @@ -17213,16 +17408,21 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v|--version] [-h|--help] [-C ПЪТ] [-c ИМЕ=СТОЙÐОСТ]\n" " [--exec-path[=ПЪТ]] [--html-path] [--man-path] [--info-path]\n" -" [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]\n" -" [--git-dir=ПЪТ] [--work-tree=ПЪТ] [--namespace=ИМЕ]\n" -" [--config-env=ИМЕ=ПРОМЕÐЛИВÐ_ÐÐ_СРЕДÐТÐ] КОМÐÐДР[ÐРГ…]" +" [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--no-lazy-" +"fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=ПЪТ]\n" +" [--work-tree=ПЪТ] [--namespace=ИМЕ] [--config-" +"env=ИМЕ=ПРОМЕÐЛИВÐ_ÐÐ_СРЕДÐТÐ]\n" +" КОМÐÐДР[ÐРГ…]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -17576,13 +17776,13 @@ msgstr "" "За да изключите това предупреждение, изпълнете:\n" " git config advice.ignoredHook false" +msgid "not a git repository" +msgstr "не е хранилище на Git" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "опциÑта „--packfile“ изиÑква валидна контролна Ñума (а не „%s“)" -msgid "not a git repository" -msgstr "не е хранилище на Git" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "" @@ -17594,6 +17794,9 @@ msgstr "Управлението на делегирането не Ñе подРmsgid "Public key pinning not supported with cURL < 7.39.0" msgstr "Задаването на поÑтоÑнен публичен ключ не Ñе поддържа от cURL < 7.39.0" +msgid "Unknown value for http.proactiveauth" +msgstr "Ðепозната ÑтойноÑÑ‚ за „http.proactiveauth“" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "„CURLSSLOPT_NO_REVOKE“ не Ñе поддържа от cURL < 7.44.0" @@ -17613,6 +17816,12 @@ msgstr "" "РеализациÑта на SSL не може да Ñе зададе да е „%s“, защото вече е зададена " "друга" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "отказ от прочитане на биÑквитките от „http.cookiefile“: „-“" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "преÑкачане на „http.savecookies“ за празен „http.cookiefile“" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17757,13 +17966,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s" +msgid "unable to create temporary object directory" +msgstr "не може да бъде Ñъздадена Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° временни обекти" + #, c-format msgid "could not write loose object index %s" msgstr "индекÑÑŠÑ‚ Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½Ð¸ обекти не може да Ñе запише: %s" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "грешка при запиÑа на индекÑа Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½Ð¸ обекти %s\n" +msgid "failed to write loose object index %s" +msgstr "грешка при запиÑа на индекÑа Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½Ð¸ обекти „%s“" #, c-format msgid "unexpected line: '%s'" @@ -17776,6 +17988,10 @@ msgid "quoted CRLF detected" msgstr "цитирани знаци CRLF" #, c-format +msgid "unable to format message: %s" +msgstr "Ñъобщението не може да Ñе форматира: %s" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (не е изтеглен)" @@ -17788,8 +18004,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (нÑма подаваниÑ)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "ГРЕШКÐ: неуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17818,12 +18034,13 @@ msgstr "" "ÐеуÑпешно Ñливане на подмодула „%s“, но Ñа открити множеÑтво решениÑ:\n" "%s" -msgid "failed to execute internal merge" -msgstr "неуÑпешно вътрешно Ñливане" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "ГРЕШКÐ: неуÑпешно вътрешно Ñливане за „%s“" #, c-format -msgid "unable to add %s to database" -msgstr "„%s“ не може да Ñе добави в базата от данни" +msgid "error: unable to add %s to database" +msgstr "ГРЕШКÐ: „%s“ не може да Ñе добави в базата от данни" #, c-format msgid "Auto-merging %s" @@ -17919,12 +18136,12 @@ msgstr "" "е изтрит в „%s“." #, c-format -msgid "cannot read object %s" -msgstr "обектът „%s“ не може да Ñе прочете" +msgid "error: cannot read object %s" +msgstr "ГРЕШКÐ: обектът „%s“ не може да Ñе прочете" #, c-format -msgid "object %s is not a blob" -msgstr "обектът „%s“ не е BLOB" +msgid "error: object %s is not a blob" +msgstr "ГРЕШКÐ: обектът „%s“ не е BLOB" #, c-format msgid "" @@ -18067,6 +18284,10 @@ msgstr "" "не е ÑÑно какво да Ñе прави Ñ Ð¾Ð±ÐµÐºÑ‚Ð° „%2$s“ (%3$s) Ñ Ð¿Ñ€Ð°Ð²Ð°Ì€ за доÑтъп „%1$06o“" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Превъртане на подмодула „%s“ до Ñледното подаване:" @@ -18108,6 +18329,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (открити Ñа множеÑтво ÑливаниÑ)" +msgid "failed to execute internal merge" +msgstr "неуÑпешно вътрешно Ñливане" + +#, c-format +msgid "unable to add %s to database" +msgstr "„%s“ не може да Ñе добави в базата от данни" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "Грешка: за да не Ñе изтрие неÑледениÑÑ‚ файл „%s“, Ñе запиÑва в „%s“." @@ -18210,6 +18438,14 @@ msgstr "" "КОÐФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " "„%s“, а „%s“ е преименуван на „%s“ в „%s“" +#, c-format +msgid "cannot read object %s" +msgstr "обектът „%s“ не може да Ñе прочете" + +#, c-format +msgid "object %s is not a blob" +msgstr "обектът „%s“ не е BLOB" + msgid "modify" msgstr "промÑна" @@ -18294,11 +18530,6 @@ msgstr "редът не може да Ñе анализира: „%s“" msgid "malformed line: %s" msgstr "неправилен ред: „%s“." -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не " -"Ñъвпада" - msgid "could not load pack" msgstr "пакетът не може да Ñе зареди" @@ -18306,6 +18537,23 @@ msgstr "пакетът не може да Ñе зареди" msgid "could not open index for %s" msgstr "индекÑÑŠÑ‚ за „%s“ не може да Ñе отвори" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "не може да Ñе Ñъздаде връзка „%s“, коÑто да Ñочи към „%s“" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде изчиÑтен при „%s“" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "" +"нараÑтващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети Ñ Ð±Ð¸Ñ‚Ð¾Ð²Ð° маÑка не може да Ñе запише" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не " +"Ñъвпада" + msgid "Adding packfiles to multi-pack-index" msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети" @@ -18333,11 +18581,25 @@ msgid "refusing to write multi-pack .bitmap without any objects" msgstr "" "многопакетната битова маÑка без никакви обекти не може да бъде запазена" +msgid "unable to create temporary MIDX layer" +msgstr "не може да Ñе Ñъздаде временен Ñлой за индекÑа за множеÑтво пакети" + msgid "could not write multi-pack bitmap" msgstr "многопакетната битова маÑка не може да бъде запазена" +msgid "unable to open multi-pack-index chain file" +msgstr "файлът Ñ Ð²ÐµÑ€Ð¸Ð³Ð°Ñ‚Ð° на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе отвори" + +msgid "unable to rename new multi-pack-index layer" +msgstr "Ñлой в индекÑа за множеÑтво пакети не може да Ñе преименува" + msgid "could not write multi-pack-index" -msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запазен" +msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да Ñе запази" + +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "" +"пакети за нараÑÑ‚Ð²Ð°Ñ‰Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети не може да Ñе обÑвÑÑ‚ за " +"оÑтарели" msgid "Counting referenced objects" msgstr "ПреброÑване на Ñвързаните обекти" @@ -18345,6 +18607,9 @@ msgstr "ПреброÑване на Ñвързаните обекти" msgid "Finding and deleting unreferenced packfiles" msgstr "ТърÑене и изтриване на неÑвързаните пакетни файлове" +msgid "cannot repack an incremental multi-pack-index" +msgstr "нараÑтващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети не може да Ñе препакетира" + msgid "could not start pack-objects" msgstr "командата „pack-objects“ не може да бъде Ñтартирана" @@ -18413,6 +18678,35 @@ msgstr "" "неправилна подредба на имената в Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети: „%s“ Ñе поÑви " "преди „%s“" +msgid "multi-pack-index chain file too small" +msgstr "файлът Ñ Ð²ÐµÑ€Ð¸Ð³Ð°Ñ‚Ð° за индекÑа за множеÑтво пакети е твърде малък" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "" +"броÑÑ‚ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð² оÑÐ½Ð¾Ð²Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети е прекалено голÑм: " +"%<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "" +"броÑÑ‚ обекти в оÑÐ½Ð¾Ð²Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети е прекалено голÑм: " +"%<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "" +"грешка във веригата на индекÑа за множеÑтво пакети: ред „%s“ не е контролна " +"Ñума" + +msgid "unable to find all multi-pack index files" +msgstr "нÑкои файлове на индекÑа за множеÑтво пакети не може да бъдат открити" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "" +"неправилна Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° обект в индекÑа за множеÑтво пакети. ВероÑтно " +"индекÑÑŠÑ‚ е повреден" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "" @@ -18435,10 +18729,6 @@ msgid "multi-pack-index large offset out of bounds" msgstr "" "ÑтойноÑтта на отмеÑтването в индекÑа за множеÑтво пакети е извън диапазона" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде изчиÑтен при „%s“" - msgid "multi-pack-index file exists, but failed to parse" msgstr "" "файлът Ñ Ð¸Ð½Ð´ÐµÐºÑа за множеÑтво пакети ÑъщеÑтвува, но не може да бъде " @@ -18664,6 +18954,14 @@ msgid "missing mapping of %s to %s" msgstr "липÑва ÑъответÑтвие на „%s“ към „%s“" #, c-format +msgid "unable to open %s" +msgstr "обектът „%s“ не може да бъде отворен" + +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "Ñъдържанието на файловете „%s“ и „%s“ е различно" + +#, c-format msgid "unable to write file %s" msgstr "файлът „%s“ не може да бъде запиÑан" @@ -18749,10 +19047,6 @@ msgid "%s is not a valid '%s' object" msgstr "„%s“ е неправилен обект от вид „%s“" #, c-format -msgid "unable to open %s" -msgstr "обектът „%s“ не може да бъде отворен" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "неправилна контролна Ñума за „%s“ (трÑбва да е %s)" @@ -18946,6 +19240,17 @@ msgstr "обектът „%s“ не може да бъде анализиран msgid "hash mismatch %s" msgstr "разлика в контролната Ñума: „%s“" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "повтарÑщ Ñе Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¸ запазване на Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки: „%s“" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "опит за ÑъхранÑване на подаване, което не е избрано: „%s“" + +msgid "too many pseudo-merges" +msgstr "прекалено много пÑевдо ÑливаниÑ" + msgid "trying to write commit not in index" msgstr "опит за запиÑване на обект за подаване извън индекÑа" @@ -18973,6 +19278,22 @@ msgstr "" "повреден файл за Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки (прекалено е малък дори и за " "таблицата ÑÑŠÑ ÑъответÑтвиÑ)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"повреден файл за Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки (прекалено е малък дори и за " +"заглавната чаÑÑ‚ на таблицата за пÑевдо ÑливаниÑта)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"повреден файл за Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки (прекалено е малък дори и за " +"таблицата Ñ Ð¿Ñевдо ÑливаниÑ)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "" +"повреден Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки, таблицата Ñ Ð¿Ñевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ðµ " +"прекалено малка" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "повтарÑщ Ñе Ð·Ð°Ð¿Ð¸Ñ Ð² Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° база битови маÑки: „%s“" @@ -19045,6 +19366,11 @@ msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "" "пакетът не може да Ñе зареди: „%s“, преизползването на пакети Ñе изключва" +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "" +"предпочитаниÑÑ‚ пакет не може да Ñе определи, преизползването на пакети Ñе " +"изключва" + #, c-format msgid "object '%s' not found in type bitmaps" msgstr "обектът „%s“ липÑва в битовата маÑка на видовете" @@ -19075,6 +19401,10 @@ msgid "mismatch in bitmap results" msgstr "различие в резултатите от битовите маÑки" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "индекÑÑŠÑ‚ за пÑевдо Ñливане е извън диапазона (%<PRIu32> ≥ %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "„%s“ липÑва в пакет „%s“ при отмеÑтване %<PRIuMAX>" @@ -19244,18 +19574,6 @@ msgstr "непознат флаг „%c“" msgid "unknown non-ascii option in string: `%s'" msgstr "непозната ÑтойноÑÑ‚ извън „ascii“ в низа: „%s“" -#, c-format -msgid "[=<%s>]" -msgstr "[=%s]" - -#, c-format -msgid "[<%s>]" -msgstr "[%s]" - -#, c-format -msgid " <%s>" -msgstr " %s" - msgid "..." msgstr "…" @@ -19468,6 +19786,9 @@ msgstr "не може да Ñе Ñъздаде нишка за изпълненРmsgid "unable to parse --pretty format" msgstr "аргументът към опциÑта „--pretty“ не може да Ñе анализира" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "отложеното доÑтавÑне е изключено, нÑкои обекти може и да липÑват" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "хранилище-гарант: неуÑпешно Ñъздаване на Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð·Ð° доÑтавÑне" @@ -19494,6 +19815,66 @@ msgstr "object-info: Ñлед аргументите Ñе очаква Ð¸Ð·Ñ‡Ð¸Ñ msgid "Removing duplicate objects" msgstr "Изтриване на повтарÑщите Ñе обекти" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "" +"регулÑрниÑÑ‚ израз за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð° „%s“, не може да бъде зареден: „%s“" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s трÑбва да е неотрицателно, ще Ñе ползва Ñтандартната ÑтойноÑÑ‚" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s трÑбва да е между 0 и 1, ще Ñе ползва Ñтандартната ÑтойноÑÑ‚" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s трÑбва да е положително, ще Ñе ползва Ñтандартната ÑтойноÑÑ‚" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "в групата за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ â€ž%s“ липÑва задължителен шаблон" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "в групата за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ â€ž%s“ има неÑтабилен праг пред ÑтабилниÑ" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"регулÑрниÑÑ‚ израз за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð² ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» Ñъдържа повече " +"от макÑимално поддържаните прихващащи групи (max=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"опит за четене на разширено пÑевдо Ñливане извън диапазона (%<PRIuMAX> ≥ " +"%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"прекалено кратък Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° разширено пÑевдо Ñливане (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "липÑва пÑевдо Ñливане за подаване „%s“ при отмеÑтване %<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"четене за група за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð´ границите (%<PRIu32> ≥ %<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "четене зад границите (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "таблицата Ñ Ñ€Ð°Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ‚Ðµ пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð° „%s“ не може да Ñе прочете" + msgid "could not start `log`" msgstr "командата за журнала Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ â€žlog“ не може да Ñе Ñтартира" @@ -19940,6 +20321,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "очакван формат: %%(ahead-behind:ПОДÐÐ’ÐÐЕ)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "очакван формат: %%(is-base:ПОДÐÐ’ÐÐЕ)" + +#, c-format msgid "malformed field name: %.*s" msgstr "неправилно име на обект: „%.*s“" @@ -20084,7 +20469,7 @@ msgstr "" " git config --global init.defaultBranch ИМЕ\n" "\n" "ЧеÑто ползвани варианти вмеÑто „master“ Ñа „main“, „trunk“ и „development“.\n" -"За да преименувата току що Ñъздаден клон, изпълнете:\n" +"За да преименувате току що Ñъздаден клон, изпълнете:\n" "\n" " git branch -m ИМЕ\n" @@ -20112,11 +20497,20 @@ msgstr "журналът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта за ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s msgid "log for %s is empty" msgstr "журналът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта за ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ е празен" +msgid "refusing to force and skip creation of reflog" +msgstr "" +"принудителна Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð±ÐµÐ· Ñъздаване на журнал на указателите нÑма да Ñе " +"приеме" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "указател не може да Ñе обнови Ñ Ð³Ñ€ÐµÑˆÐ½Ð¾ име „%s“" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "пÑевдо указателÑÑ‚ „%s“ нÑма да Ñе обнови" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "неуÑпешно обновÑване на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ (update_ref) „%s“: %s" @@ -20147,6 +20541,32 @@ msgid "could not delete references: %s" msgstr "Указателите не може да бъдат изтрити: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "Пробната Ð¼Ð¸Ð³Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° указатели завърши, резултатите Ñа в „%s“\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "временната Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° Ð¼Ð¸Ð³Ñ€Ð°Ñ†Ð¸Ñ â€ž%s“ не може да Ñе изтрие" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "мигрираните указатели Ñа в „%s“" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"указателÑÑ‚ „%s“ не може да Ñе заключи: очакваше Ñе файл Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» Ñ Ñ†ÐµÐ» " +"„%s“, но вмеÑто това е обикновен указател" + +#, c-format +msgid "cannot open directory %s" +msgstr "директориÑта „%s“ не може да бъде отворена" + +msgid "Checking references consistency" +msgstr "Проверка на валидноÑтта на указателите" + +#, c-format msgid "refname is dangerous: %s" msgstr "опаÑно име на указател: %s" @@ -20695,7 +21115,7 @@ msgid "" "--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " "REVERT_HEAD or REBASE_HEAD" msgstr "" -"„--merge“ изиÑква нÑкой от пÑевдоуказателите „MERGE_HEAD“, " +"„--merge“ изиÑква нÑкой от пÑевдо указателите „MERGE_HEAD“, " "„CHERRY_PICK_HEAD“, „REVERT_HEAD“ или „REBASE_HEAD“" #, c-format @@ -20800,12 +21220,15 @@ msgstr "да Ñе ÑвалÑÑ‚ метаданните Ñамо за изтегл msgid "create repository within 'src' directory" msgstr "Ñъздаване на хранилище в Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ â€žsrc“" +msgid "specify if tags should be fetched during clone" +msgstr "указва дали етикетите да Ñе доÑтавÑÑ‚ при клониране" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch ОСÐОВЕÐ_КЛОÐ] [--full-clone]\n" -" [--[no-]src] ÐДРЕС [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" +" [--[no-]src] [--[no-]tags] ÐДРЕС [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -20824,6 +21247,10 @@ msgid "could not configure remote in '%s'" msgstr "отдалеченото хранилище в „%s“ не може да Ñе наÑтрои" #, c-format +msgid "could not disable tags in '%s'" +msgstr "етикетите в „%s“ не може Ñа Ñе изключат" + +#, c-format msgid "could not configure '%s'" msgstr "„%s“ не може да Ñе наÑтрои" @@ -21357,6 +21784,56 @@ msgstr "" "командата „update-ref“ изиÑква пълно име на указател, напр. „refs/heads/%s“" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "„%s“ не приема Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ ÑÑŠÑ Ñливане" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"„pick“ не приема подаване ÑÑŠÑ Ñливане. Ðко иÑкате да приложите\n" +"Ñливането наново изпълнате:\n" +"\n" +" git merge -C ПОДÐÐ’ÐÐЕ" + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"„reword“ не приема подаване ÑÑŠÑ Ñливане. Ðко иÑкате да приложите\n" +"Ñливането наново и да промените Ñъобщението при подаване, изпълнете\n" +"\n" +" git merge -C ПОДÐÐ’ÐÐЕ" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"„edit“ не приема подаване ÑÑŠÑ Ñливане. Ðко иÑкате да приложите\n" +"Ñливането наново, изпълнете\n" +"\n" +" git merge -C ПОДÐÐ’ÐÐЕ\n" +"\n" +"а Ñлед него задайте „break“, за да получите контрол и да изпълнете:\n" +"\n" +" git commit --amend && git rebase --continue" + +msgid "cannot squash merge commit into another commit" +msgstr "подаване ÑÑŠÑ Ñливане не може да Ñе вкара в друго" + +#, c-format msgid "invalid command '%.*s'" msgstr "неправилна команда „%.*s“" @@ -21483,9 +21960,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "указателÑÑ‚ „HEAD“ не може да бъде прочетен" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "„%s“ не може да Ñе копира като „%s“" +msgid "could not write commit message file" +msgstr "файлът ÑÑŠÑ Ñъобщението за подаване не може да бъде запиÑан" #, c-format msgid "" @@ -21894,6 +22370,22 @@ msgstr "процеÑÑŠÑ‚ не може да Ñе върне към предишРmsgid "failed to stat '%*s%s%s'" msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%*s%s%s“" +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "пътÑÑ‚ за безопаÑна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ (safe.directory) „%s“ не е абÑолютен" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"заÑечено е проблемно притежание на хранилището „%s“\n" +"%sЗа да зададете изключение за тази директориÑ, изпълнете:\n" +"\n" +" git config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да бъде прочетена" @@ -21918,18 +22410,6 @@ msgstr "" "„GIT_DISCOVERY_ACROSS_FILESYSTEM“ не е зададена." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"заÑечено е проблемно притежание на хранилището „%s“\n" -"%sЗа да зададете изключение за тази директориÑ, изпълнете:\n" -"\n" -" git config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "" "голото хранилище „%s“ не може да Ñе ползва („safe.bareRepository“ е „%s“)" @@ -22241,6 +22721,14 @@ msgid "submodule git dir '%s' is inside git dir '%.*s'" msgstr "„%s“ (Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° подмодул) е в директориÑта на git: „%.*s“" #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "„%.*s“ в Ð¿ÑŠÑ‚Ñ Ð·Ð° подмодул „%s“ не трÑбва да е Ñимволна връзка" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "пътÑÑ‚ за подмодул „%s“ не трÑбва да е Ñимволна връзка" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -22279,10 +22767,6 @@ msgstr "не може Ð´Ð° бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€Ðµ msgid "no remote configured to get bundle URIs from" msgstr "не е наÑтроено отдалечено хранилище за ÑпиÑъците Ñ Ð°Ð´Ñ€ÐµÑи на пратки" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "не е зададен никакъв Ð°Ð´Ñ€ÐµÑ Ð·Ð° отдалеченото хранилище„%s“" - msgid "could not get the bundle-uri list" msgstr "ÑпиÑъкът Ñ Ð°Ð´Ñ€ÐµÑи на пратки не може да Ñе получи" @@ -22365,6 +22849,24 @@ msgstr "лекÑема" msgid "command token to send to the server" msgstr "командна лекÑема за пращане" +msgid "unit-test [<options>]" +msgstr "unit-test [ОПЦИЯ…]" + +msgid "immediately exit upon the first failed test" +msgstr "незабавен изход Ñлед Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð½ÐµÑƒÑпешен теÑÑ‚" + +msgid "suite[::test]" +msgstr "ГРУПÐ[::ТЕСТ]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "изпълнение на тази ГРУПРили конкретен теÑÑ‚ Ñ Ð¸Ð¼Ðµ ГРУПÐ::ТЕСТ" + +msgid "suite" +msgstr "ГРУПÐ" + +msgid "exclude test suite <suite>" +msgstr "преÑкачане на тази ГРУПРтеÑтове" + #, c-format msgid "running trailer command '%s' failed" msgstr "неуÑпешно изпълнение на завършващата команда „%s“" @@ -22614,7 +23116,7 @@ msgstr "операциÑта „bundle-uri“ (адреÑи на пратки) Ð msgid "could not retrieve server-advertised bundle-uri list" msgstr "" -"ÑпъÑъкът Ñ Ð°Ð´Ñ€ÐµÑи на пратки обÑвени за налични от Ñървъра не може да Ñе " +"ÑпиÑъкът Ñ Ð°Ð´Ñ€ÐµÑи на пратки обÑвени за налични от Ñървъра не може да Ñе " "получи " msgid "operation not supported by protocol" @@ -23379,7 +23881,7 @@ msgid "" "but the results were cached, and subsequent runs may be faster." msgstr "" "ИзброÑването на неÑледените файлове отне %.2f Ñекунди, но\n" -"резултатите Ñа запомнени и може да забързат поÑледващиге изброÑваниÑ." +"резултатите Ñа запомнени и може да забързат поÑледващите изброÑваниÑ." #, c-format msgid "It took %.2f seconds to enumerate untracked files." @@ -23567,6 +24069,9 @@ msgstr "„%s.final“ Ñъдържа подготвеното е-пиÑмо.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "опциÑта „--dump-aliases“ е неÑъвмеÑтима Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ‚Ðµ опции\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "опциите „--dump-aliases“ и „--translate-aliases“ Ñа неÑъвмеÑтими\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -23785,24 +24290,24 @@ msgid "Failed to send %s\n" msgstr "„%s“ не може да бъде изпратен\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Проба за изпращане на „%s“\n" +msgid "Dry-Sent %s" +msgstr "Проба за изпращане на „%s“" #, perl-format -msgid "Sent %s\n" -msgstr "Изпращане на „%s“\n" +msgid "Sent %s" +msgstr "Изпращане на „%s“" -msgid "Dry-OK. Log says:\n" -msgstr "УÑпех при пробата. От журнала:\n" +msgid "Dry-OK. Log says:" +msgstr "УÑпех при пробата. От журнала:" -msgid "OK. Log says:\n" -msgstr "УÑпех. От журнала:\n" +msgid "OK. Log says:" +msgstr "УÑпех. От журнала:" msgid "Result: " msgstr "Резултат: " -msgid "Result: OK\n" -msgstr "Резултат: уÑпех\n" +msgid "Result: OK" +msgstr "Резултат: уÑпех" #, perl-format msgid "can't open file %s" @@ -77,186 +77,238 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-02-16 07:14+0100\n" -"PO-Revision-Date: 2024-02-16 07:16+0100\n" -"Last-Translator: Jordi Mas i Hernà ndez <jmas@softcatala.org>\n" +"POT-Creation-Date: 2024-10-05 01:20+0000\n" +"PO-Revision-Date: 2024-10-05 09:03+0200\n" +"Last-Translator: Mikel Forcada <mikel.forcada@gmail.com>\n" "Language-Team: Catalan\n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.3.1\n" +"X-Generator: Poedit 3.2.2\n" +#: add-interactive.c #, c-format msgid "Huh (%s)?" msgstr "Perdó (%s)?" +#: add-interactive.c builtin/merge.c builtin/rebase.c reset.c sequencer.c msgid "could not read index" msgstr "no s'ha pogut llegir l'Ãndex" +#: add-interactive.c msgid "binary" msgstr "binari" +#: add-interactive.c msgid "nothing" msgstr "res" +#: add-interactive.c msgid "unchanged" msgstr "sense canvis" +#: add-interactive.c msgid "Update" msgstr "Actualitza" +#: add-interactive.c #, c-format msgid "could not stage '%s'" msgstr "no s'ha pogut fer «stage» «%s»" +#: add-interactive.c builtin/stash.c reset.c sequencer.c msgid "could not write index" msgstr "no s'ha pogut escriure l'Ãndex" +#: add-interactive.c #, c-format msgid "updated %d path\n" msgid_plural "updated %d paths\n" msgstr[0] "actualitzat %d camÃ\n" msgstr[1] "actualitzats %d camins\n" +#: add-interactive.c #, c-format msgid "note: %s is untracked now.\n" msgstr "nota: %s està ara sense seguiment.\n" +#: add-interactive.c apply.c builtin/checkout.c builtin/reset.c #, c-format msgid "make_cache_entry failed for path '%s'" msgstr "make_cache_entry ha fallat per al camà «%s»" +#: add-interactive.c msgid "Revert" msgstr "Reverteix" +#: add-interactive.c msgid "Could not parse HEAD^{tree}" msgstr "No s'ha pogut analitzar HEAD^{tree}" +#: add-interactive.c #, c-format msgid "reverted %d path\n" msgid_plural "reverted %d paths\n" msgstr[0] "revertit %d camÃ\n" msgstr[1] "revertits %d camins\n" +#: add-interactive.c #, c-format msgid "No untracked files.\n" msgstr "Sense fitxers no seguits.\n" +#: add-interactive.c msgid "Add untracked" msgstr "Afegeix sense seguiment" +#: add-interactive.c #, c-format msgid "added %d path\n" msgid_plural "added %d paths\n" msgstr[0] "afegit %d camÃ\n" msgstr[1] "afegits %d camins\n" +#: add-interactive.c #, c-format msgid "ignoring unmerged: %s" msgstr "s'està ignorant allò no fusionat: %s" +#: add-interactive.c #, c-format msgid "Only binary files changed.\n" msgstr "Només han canviat fitxers binaris.\n" +#: add-interactive.c #, c-format msgid "No changes.\n" msgstr "Sense canvis.\n" +#: add-interactive.c msgid "Patch update" msgstr "Actualització del pedaç" +#: add-interactive.c msgid "Review diff" msgstr "Reviseu les diferències" +#: add-interactive.c msgid "show paths with changes" msgstr "mostra els camins amb canvis" +#: add-interactive.c msgid "add working tree state to the staged set of changes" msgstr "afegeix l'estat de l'arbre de treball al conjunt de canvis «staged»" +#: add-interactive.c msgid "revert staged set of changes back to the HEAD version" msgstr "reverteix el conjunt de canvis «staged» a la versió HEAD" +#: add-interactive.c msgid "pick hunks and update selectively" msgstr "selecciona els trossos i actualitza selectivament" +#: add-interactive.c msgid "view diff between HEAD and index" msgstr "visualitza les diferències entre HEAD i l'Ãndex" +#: add-interactive.c msgid "add contents of untracked files to the staged set of changes" msgstr "afegeix contingut de fitxers no seguits al conjunt de canvis «staged»" +#: add-interactive.c msgid "Prompt help:" msgstr "Mostra ajuda:" +#: add-interactive.c msgid "select a single item" msgstr "seleccioneu un únic Ãtem" +#: add-interactive.c msgid "select a range of items" msgstr "seleccioneu un rang d'Ãtems" +#: add-interactive.c msgid "select multiple ranges" msgstr "seleccioneu rangs múltiples" +#: add-interactive.c msgid "select item based on unique prefix" msgstr "seleccioneu un Ãtem basant-se en un prefix únic" +#: add-interactive.c msgid "unselect specified items" msgstr "desselecciona els Ãtems especificats" +#: add-interactive.c msgid "choose all items" msgstr "trieu tots els Ãtems" +#: add-interactive.c msgid "(empty) finish selecting" msgstr "(buit) finalitza la selecció" +#: add-interactive.c msgid "select a numbered item" msgstr "seleccioneu un Ãtem numerat" +#: add-interactive.c msgid "(empty) select nothing" msgstr "(buit) no seleccionis res" +#: add-interactive.c builtin/clean.c msgid "*** Commands ***" msgstr "*** Ordres ***" +#: add-interactive.c builtin/clean.c msgid "What now" msgstr "I ara què" +#: add-interactive.c msgid "staged" msgstr "staged" +#: add-interactive.c msgid "unstaged" msgstr "unstaged" +#: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c +#: builtin/diagnose.c builtin/fetch.c builtin/hook.c builtin/merge.c +#: builtin/pull.c builtin/submodule--helper.c msgid "path" msgstr "camÃ" +#: add-interactive.c msgid "could not refresh index" msgstr "no s'ha pogut actualitzar l'Ãndex" +#: add-interactive.c builtin/clean.c #, c-format msgid "Bye.\n" msgstr "Adeu.\n" +#: add-patch.c #, c-format msgid "Stage mode change [y,n,q,a,d%s,?]? " msgstr "Canvia el mode de «stage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stage deletion [y,n,q,a,d%s,?]? " msgstr "Suprimeix «stage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stage addition [y,n,q,a,d%s,?]? " msgstr "Afegeix a «stage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stage this hunk [y,n,q,a,d%s,?]? " msgstr "Fer un «stage» d'aquest tros [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "staging." @@ -264,6 +316,7 @@ msgstr "" "Si el pedaç s'aplica netament, el tros editat es marcarà immediatament per a " "«staging»." +#: add-patch.c msgid "" "y - stage this hunk\n" "n - do not stage this hunk\n" @@ -275,24 +328,30 @@ msgstr "" "n - no facis «stage» d'aquest tros\n" "q - surt; no facis «stage» d'aquest tros ni de cap altre restant\n" "a - fes «stage» d'aquest tros i de tota la resta de trossos del fitxer\n" -"d - no facis «stage» d'aquest tros ni de cap altre restant del fitxer\n" +"d - no facis «stage» d'aquest tros ni de cap altre tros posterior del " +"fitxer\n" +#: add-patch.c #, c-format msgid "Stash mode change [y,n,q,a,d%s,?]? " msgstr "Canvia el mode de «stash» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stash deletion [y,n,q,a,d%s,?]? " msgstr "Suprimeix «stash» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stash addition [y,n,q,a,d%s,?]? " msgstr "Afegeix a «stash» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Stash this hunk [y,n,q,a,d%s,?]? " msgstr "Fer un «stash» d'aquest tros [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "stashing." @@ -300,6 +359,7 @@ msgstr "" "Si el pedaç s'aplica de forma neta, el tros editat es marcarà immediatament " "per a «stashing»." +#: add-patch.c msgid "" "y - stash this hunk\n" "n - do not stash this hunk\n" @@ -311,24 +371,30 @@ msgstr "" "n - no facis «stash» d'aquest tros\n" "q - surt; no facis «stash» d'aquest tros ni de cap altre restant\n" "a - fes «stash» d'aquest tros i de tota la resta de trossos del fitxer\n" -"d - no facis «stash» d'aquest tros ni de cap altre restant del fitxer\n" +"d - no facis «stash» d'aquest tros ni de cap altre tros posterior del " +"fitxer\n" +#: add-patch.c #, c-format msgid "Unstage mode change [y,n,q,a,d%s,?]? " msgstr "Canvia el mode de «unstage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Unstage deletion [y,n,q,a,d%s,?]? " msgstr "Suprimeix «Unstage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Unstage addition [y,n,q,a,d%s,?]? " msgstr "Afegeix a «unstage» [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Unstage this hunk [y,n,q,a,d%s,?]? " msgstr "Fer un «unstage» d'aquest tros [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "unstaging." @@ -336,6 +402,7 @@ msgstr "" "Si el pedaç s'aplica netament, el tros editat es marcarà immediatament per a " "«unstaging»." +#: add-patch.c msgid "" "y - unstage this hunk\n" "n - do not unstage this hunk\n" @@ -349,22 +416,27 @@ msgstr "" "a - fes «unstage» d'aquest tros i de tota la resta de trossos del fitxer\n" "d - no facis «unstage» d'aquest tros ni de cap altre restant del fitxer\n" +#: add-patch.c #, c-format msgid "Apply mode change to index [y,n,q,a,d%s,?]? " msgstr "Aplica el canvi de mode a l'Ãndex [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply deletion to index [y,n,q,a,d%s,?]? " msgstr "Aplica la supressió a l'Ãndex [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply addition to index [y,n,q,a,d%s,?]? " msgstr "Aplica l'addició a l'Ãndex [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply this hunk to index [y,n,q,a,d%s,?]? " msgstr "Aplica aquest tros a l'Ãndex [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "applying." @@ -372,6 +444,7 @@ msgstr "" "Si el pedaç s'aplica netament, el tros editat es marcarà immediatament per a " "aplicar-lo." +#: add-patch.c msgid "" "y - apply this hunk to index\n" "n - do not apply this hunk to index\n" @@ -385,22 +458,27 @@ msgstr "" "a - aplica aquest tros i tots els trossos posteriors en el fitxer\n" "d - no apliquis aquest tros ni cap dels trossos posteriors en el fitxer\n" +#: add-patch.c #, c-format msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? " msgstr "Descarta el canvi de mode de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? " msgstr "Descarta suprimir de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Discard addition from worktree [y,n,q,a,d%s,?]? " msgstr "Descarta l'addició de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? " msgstr "Descarta aquest tros de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "discarding." @@ -408,6 +486,7 @@ msgstr "" "Si el pedaç s'aplica netament, el tros editat es marcarà immediatament per a " "ser descartat." +#: add-patch.c msgid "" "y - discard this hunk from worktree\n" "n - do not discard this hunk from worktree\n" @@ -421,26 +500,31 @@ msgstr "" "a - descarta aquest tros i tots els trossos posteriors en el fitxer\n" "d - no descartis aquest tros ni cap dels trossos posteriors en el fitxer\n" +#: add-patch.c #, c-format msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? " msgstr "" "Descarta el canvi de mode de l'Ãndex i de l'arbre de treball [y,n,q,a," "d%s,?]? " +#: add-patch.c #, c-format msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? " msgstr "Descarta suprimir de l'Ãndex i de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? " msgstr "" "Descarta l'addició de l'Ãndex i de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " msgstr "" "Descarta aquest tros de l'Ãndex i de l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "y - discard this hunk from index and worktree\n" "n - do not discard this hunk from index and worktree\n" @@ -454,23 +538,28 @@ msgstr "" "a - descarta aquest tros i tots els trossos posteriors en el fitxer\n" "d - no descartis aquest tros ni cap dels trossos posteriors en el fitxer\n" +#: add-patch.c #, c-format msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? " msgstr "" "Aplica el canvi de mode a l'Ãndex i a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? " msgstr "Aplica la supressió a l'Ãndex i a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? " msgstr "Aplica l'addició a l'Ãndex i a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " msgstr "Aplica aquest tros a l'Ãndex i a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "y - apply this hunk to index and worktree\n" "n - do not apply this hunk to index and worktree\n" @@ -484,22 +573,27 @@ msgstr "" "a - aplica aquest tros i tots els trossos posteriors en el fitxer\n" "d - no apliquis aquest tros ni cap dels trossos posteriors en el fitxer\n" +#: add-patch.c #, c-format msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? " msgstr "Aplica el canvi de mode a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? " msgstr "Aplica la supressió a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply addition to worktree [y,n,q,a,d%s,?]? " msgstr "Aplica l'addició a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c #, c-format msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? " msgstr "Aplica aquest tros a l'arbre de treball [y,n,q,a,d%s,?]? " +#: add-patch.c msgid "" "y - apply this hunk to worktree\n" "n - do not apply this hunk to worktree\n" @@ -513,23 +607,29 @@ msgstr "" "a - aplica aquest tros i tots els trossos posteriors en el fitxer\n" "d - no apliquis aquest tros ni cap dels trossos posteriors en el fitxer\n" +#: add-patch.c #, c-format msgid "could not parse hunk header '%.*s'" msgstr "no s'ha pogut analitzar la capçalera del tros «%.*s»" +#: add-patch.c msgid "could not parse diff" msgstr "no s'ha pogut analitzar el diff" +#: add-patch.c msgid "could not parse colored diff" msgstr "no s'ha pogut analitzar el diff acolorit" +#: add-patch.c #, c-format msgid "failed to run '%s'" msgstr "no s'ha pogut executar «%s»" +#: add-patch.c msgid "mismatched output from interactive.diffFilter" msgstr "sortida no coincident des d'interactive.diffFilter" +#: add-patch.c msgid "" "Your filter must maintain a one-to-one correspondence\n" "between its input and output lines." @@ -537,6 +637,7 @@ msgstr "" "El filtre ha de mantenir una correspondència d'un a un\n" "entre les lÃnies d'entrada i sortida." +#: add-patch.c #, c-format msgid "" "expected context line #%d in\n" @@ -545,6 +646,7 @@ msgstr "" "s'esperava la lÃnia amb contingut #%d a\n" "%.*s" +#: add-patch.c #, c-format msgid "" "hunks do not overlap:\n" @@ -557,22 +659,25 @@ msgstr "" "\tno acaben amb:\n" "%.*s" +#: add-patch.c msgid "Manual hunk edit mode -- see bottom for a quick guide.\n" msgstr "" "Mode d'edició de trossos manual - vegeu més avall per a una guia rà pida.\n" +#: add-patch.c #, c-format msgid "" "---\n" "To remove '%c' lines, make them ' ' lines (context).\n" "To remove '%c' lines, delete them.\n" -"Lines starting with %c will be removed.\n" +"Lines starting with %s will be removed.\n" msgstr "" "---\n" "Per a eliminar les lÃnies «%c», convertiu-les en lÃnies ' ' (context).\n" "Per a eliminar les lÃnies «%c», suprimiu-les.\n" -"Les lÃnies que comencin per %c s'eliminaran.\n" +"Les lÃnies que comencin per %s s'eliminaran.\n" +#: add-patch.c msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" "edit again. If all lines of the hunk are removed, then the edit is\n" @@ -582,9 +687,11 @@ msgstr "" "de nou. Si s'eliminen totes les lÃnies del tros, llavors l'edició s'avorta\n" "i el tros es deixa sense cap canvi.\n" +#: add-patch.c msgid "could not parse hunk header" msgstr "no s'ha pogut analitzar la capçalera del tros" +#: add-patch.c msgid "'git apply --cached' failed" msgstr "«git apply --cached» ha fallat" @@ -594,21 +701,26 @@ msgstr "«git apply --cached» ha fallat" #. (saying "n" for "no" discards!) if the translation #. of the word "no" does not start with n. #. +#: add-patch.c msgid "" "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " msgstr "" "El tros editat no s'aplica. Editeu-lo de nou (si responeu «no» es " "descartarà ) [y/n]? " +#: add-patch.c msgid "The selected hunks do not apply to the index!" msgstr "Els trossos seleccionats no s'apliquen a l'Ãndex!" +#: add-patch.c msgid "Apply them to the worktree anyway? " msgstr "Voleu aplicar-los igualment a l'arbre de treball? " +#: add-patch.c msgid "Nothing was applied.\n" msgstr "No s'ha aplicat res.\n" +#: add-patch.c msgid "" "j - leave this hunk undecided, see next undecided hunk\n" "J - leave this hunk undecided, see next hunk\n" @@ -618,69 +730,105 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" -"j - deixa aquest tros sense decidir, veure el tros sense decidir següent\n" -"J - deixa aquest tros sense decidir, veure el tros següent\n" -"k - deixa aquest tros sense decidir, veure el tros sense decidir anterior\n" -"K - deixa aquest tros sense decidir, veure el tros anterior\n" -"g - selecciona el tros on voleu anar\n" -"/ - cerca un tros que coincideixi amb l'expressió regular donada\n" -"s - divideix el tros actual en trossos més petits\n" +"j - deixa aquest tros sense decidir, veges el tros següent no decidit \n" +"J - deixa aquest tros sense decidir, veges el tros següent\n" +"k - deixa aquest tros sense decidir, veges el tros anterior no decidit ºn\n" +"K - deixa aquest tros sense decidir, veges el tros anterior\n" +"g - selecciona un tros a on anar\n" +"/ - cerca un tros que concorde amb l'expressió regular donada\n" +"s - divideix el tros actual en trossos més menuts\n" "e - edita manualment el tros actual\n" -"? - mostra l'ajuda\n" +"p - imprimeix el tros actual, «P» per a usar el paginador\n" +"? - imprimeix l'ajuda\n" +#: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "S'espera una lletra, s'ha obtingut «%s»" + +#: add-patch.c msgid "No previous hunk" msgstr "Sense tros previ" +#: add-patch.c msgid "No next hunk" msgstr "No hi ha tros següent" +#: add-patch.c msgid "No other hunks to goto" msgstr "No hi ha altres trossos on anar-hi" +#: add-patch.c msgid "go to which hunk (<ret> to see more)? " -msgstr "ves a quin tros (<ret> per a veure'n més)? " +msgstr "ves a quin tros (<intro> per a veure'n més)? " +#: add-patch.c msgid "go to which hunk? " msgstr "ves a quin tros? " +#: add-patch.c #, c-format msgid "Invalid number: '%s'" msgstr "Número no và lid: «%s»" +#: add-patch.c #, c-format msgid "Sorry, only %d hunk available." msgid_plural "Sorry, only %d hunks available." msgstr[0] "Només %d tros disponible." msgstr[1] "Només %d trossos disponibles." +#: add-patch.c msgid "No other hunks to search" msgstr "No hi ha cap altre tros a cercar" +#: add-patch.c msgid "search for regex? " msgstr "cerca per expressió regular? " +#: add-patch.c #, c-format msgid "Malformed search regexp %s: %s" msgstr "Expressió regular de cerca mal formada %s: %s" +#: add-patch.c msgid "No hunk matches the given pattern" msgstr "No hi ha trossos que coincideixin amb el patró donat" +#: add-patch.c msgid "Sorry, cannot split this hunk" msgstr "No es pot dividir aquest tros" +#: add-patch.c #, c-format msgid "Split into %d hunks." msgstr "Divideix en %d trossos." +#: add-patch.c msgid "Sorry, cannot edit this hunk" msgstr "No es pot editar aquest tros" +#: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Ordre desconeguda: «%s» (useu «?» per a obtenir ajuda)" + +#: add-patch.c msgid "'git apply' failed" msgstr "«git apply» ha fallat" +#: add-patch.c +msgid "No changes." +msgstr "No hi ha canvis." + +#: add-patch.c +msgid "Only binary files changed." +msgstr "Només han canviat els fitxers binaris." + +#: advice.c #, c-format msgid "" "\n" @@ -689,28 +837,36 @@ msgstr "" "\n" "Desactiva aquest missatge amb «git config advice.%s false»" +#: advice.c #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sconsell: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sconsell:%s%.*s%s\n" +#: advice.c msgid "Cherry-picking is not possible because you have unmerged files." msgstr "Fer «cherry pick» no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "Committing is not possible because you have unmerged files." msgstr "Cometre no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "Merging is not possible because you have unmerged files." msgstr "Fusionar no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "Pulling is not possible because you have unmerged files." msgstr "Baixar no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "Reverting is not possible because you have unmerged files." msgstr "Revertir no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "Rebasing is not possible because you have unmerged files." msgstr "Fer «rebase» no és possible perquè teniu fitxers sense fusionar." +#: advice.c msgid "" "Fix them up in the work tree, and then use 'git add/rm <file>'\n" "as appropriate to mark resolution and make a commit." @@ -719,18 +875,23 @@ msgstr "" "«git add/rm <fitxer>» segons sigui apropiat per a\n" "marcar la resolució i feu una comissió." +#: advice.c msgid "Exiting because of an unresolved conflict." msgstr "S'està sortint a causa d'un conflicte no resolt." +#: advice.c builtin/merge.c msgid "You have not concluded your merge (MERGE_HEAD exists)." msgstr "No heu conclòs la vostra fusió (MERGE_HEAD existeix)." +#: advice.c msgid "Please, commit your changes before merging." msgstr "Cometeu els vostres canvis abans de fusionar." +#: advice.c msgid "Exiting because of unfinished merge." msgstr "S'està sortint a causa d'una fusió no terminada." +#: advice.c msgid "" "Diverging branches can't be fast-forwarded, you need to either:\n" "\n" @@ -748,9 +909,11 @@ msgstr "" "\n" "\tgit rebase\n" +#: advice.c msgid "Not possible to fast-forward, aborting." msgstr "No és possible avançar rà pidament, s'està avortant." +#: advice.c #, c-format msgid "" "The following paths and/or pathspecs matched paths that exist\n" @@ -761,6 +924,7 @@ msgstr "" "amb camins que existeixen fora de la vostra definició de\n" "«sparse-checkout», aixà que no serà actualitzaran en l'Ãndex:\n" +#: advice.c msgid "" "If you intend to update such entries, try one of the following:\n" "* Use the --sparse option.\n" @@ -770,6 +934,7 @@ msgstr "" "* Utilitzeu l'opció --sparse.\n" "* Inhabiliteu o modifiqueu les regles de dispersió." +#: advice.c #, c-format msgid "" "Note: switching to '%s'.\n" @@ -810,6 +975,7 @@ msgstr "" "«false»\n" "\n" +#: advice.c #, c-format msgid "" "The following paths have been moved outside the\n" @@ -820,6 +986,7 @@ msgstr "" "definició de sparse-checkout però no són dispersos\n" "a causa de modificacions en local.\n" +#: advice.c msgid "" "To correct the sparsity of these paths, do the following:\n" "* Use \"git add --sparse <paths>\" to update the index\n" @@ -829,79 +996,108 @@ msgstr "" "* Useu «git add --sparse <paths>» per a actualitzar l'Ãndex\n" "* Useu «git sparse-checkout reapply» per a aplicar les regles de dispersió" +#: alias.c msgid "cmdline ends with \\" msgstr "la lÃnia d'ordres acaba amb \\" +#: alias.c msgid "unclosed quote" msgstr "cometes no tancades" +#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c msgid "too many arguments" msgstr "hi ha massa arguments" +#: apply.c #, c-format msgid "unrecognized whitespace option '%s'" msgstr "opció d'espai en blanc «%s» no reconeguda" +#: apply.c #, c-format msgid "unrecognized whitespace ignore option '%s'" msgstr "opció ignora l'espai en blanc «%s» no reconeguda" +#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c +#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c +#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c +#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c +#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c +#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c +#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c +#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c +#: range-diff.c revision.c #, c-format msgid "options '%s' and '%s' cannot be used together" msgstr "les opcions «%s» i «%s» no es poden usar juntes" +#: apply.c #, c-format msgid "'%s' outside a repository" msgstr "«%s» fora d'un repositori" +#: apply.c msgid "failed to read patch" msgstr "s'ha produït un error en llegir el pedaç" +#: apply.c msgid "patch too large" msgstr "el pedaç és massa gran" +#: apply.c #, c-format msgid "Cannot prepare timestamp regexp %s" msgstr "No es pot preparar l'expressió regular de marca de temps %s" +#: apply.c #, c-format msgid "regexec returned %d for input: %s" msgstr "regexec ha retornat %d per a l'entrada: %s" +#: apply.c #, c-format msgid "unable to find filename in patch at line %d" msgstr "no s'ha pogut trobar el nom de fitxer en el pedaç a la lÃnia %d" +#: apply.c #, c-format msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" msgstr "" "git apply: git-diff incorrecte - s'esperava /dev/null, s'ha rebut %s en la " "lÃnia %d" +#: apply.c #, c-format msgid "git apply: bad git-diff - inconsistent new filename on line %d" msgstr "" "git apply: git-diff incorrecte - nom de fitxer nou inconsistent en la lÃnia " "%d" +#: apply.c #, c-format msgid "git apply: bad git-diff - inconsistent old filename on line %d" msgstr "" "git apply: git-diff incorrecte - nom de fitxer antic inconsistent en la " "lÃnia %d" +#: apply.c #, c-format msgid "git apply: bad git-diff - expected /dev/null on line %d" msgstr "git apply: git-diff incorrecte - s'esperava /dev/null en la lÃnia %d" +#: apply.c #, c-format msgid "invalid mode on line %d: %s" msgstr "mode no và lid en la lÃnia %d: %s" +#: apply.c #, c-format msgid "inconsistent header lines %d and %d" msgstr "lÃnies de capçalera %d i %d inconsistents" +#: apply.c #, c-format msgid "" "git diff header lacks filename information when removing %d leading pathname " @@ -916,75 +1112,93 @@ msgstr[1] "" "a la capçalera de git diff li manca informació de nom de fitxer en eliminar " "%d components de nom de camà inicial (lÃnia %d)" +#: apply.c #, c-format msgid "git diff header lacks filename information (line %d)" msgstr "" "a la capçalera de git diff li manca informació de nom de fitxer (lÃnia %d)" +#: apply.c #, c-format msgid "recount: unexpected line: %.*s" msgstr "recompte: lÃnia inesperada: %.*s" +#: apply.c #, c-format msgid "patch fragment without header at line %d: %.*s" msgstr "fragment de pedaç sense capçalera a la lÃnia %d: %.*s" +#: apply.c msgid "new file depends on old contents" msgstr "el fitxer nou depèn dels continguts antics" +#: apply.c msgid "deleted file still has contents" msgstr "el fitxer suprimit encara té continguts" +#: apply.c #, c-format msgid "corrupt patch at line %d" msgstr "pedaç malmès a la lÃnia %d" +#: apply.c #, c-format msgid "new file %s depends on old contents" msgstr "el fitxer nou %s depèn dels continguts antics" +#: apply.c #, c-format msgid "deleted file %s still has contents" msgstr "el fitxer suprimit %s encara té continguts" +#: apply.c #, c-format msgid "** warning: file %s becomes empty but is not deleted" msgstr "** advertència: el fitxer %s queda buit però no se suprimeix" +#: apply.c #, c-format msgid "corrupt binary patch at line %d: %.*s" msgstr "pedaç binari malmès a la lÃnia %d: %.*s" +#: apply.c #, c-format msgid "unrecognized binary patch at line %d" msgstr "pedaç binari no reconegut a la lÃnia %d" +#: apply.c #, c-format msgid "patch with only garbage at line %d" msgstr "pedaç amb només escombraries a la lÃnia %d" +#: apply.c #, c-format msgid "unable to read symlink %s" msgstr "no s'ha pogut llegir l'enllaç simbòlic %s" +#: apply.c #, c-format msgid "unable to open or read %s" msgstr "no s'ha pogut obrir o llegir %s" +#: apply.c #, c-format msgid "invalid start of line: '%c'" msgstr "inici de lÃnia no và lid: «%c»" +#: apply.c #, c-format msgid "Hunk #%d succeeded at %d (offset %d line)." msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." msgstr[0] "El tros #%d ha tingut èxit a %d (desplaçament d'%d lÃnia)." msgstr[1] "El tros #%d ha tingut èxit a %d (desplaçament de %d lÃnies)." +#: apply.c #, c-format msgid "Context reduced to (%ld/%ld) to apply fragment at %d" msgstr "El context s'ha reduït a (%ld/%ld) per a aplicar el fragment a %d" +#: apply.c #, c-format msgid "" "while searching for:\n" @@ -993,19 +1207,23 @@ msgstr "" "tot cercant:\n" "%.*s" +#: apply.c #, c-format msgid "missing binary patch data for '%s'" msgstr "manquen les dades de pedaç binari de «%s»" +#: apply.c #, c-format msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" msgstr "no es pot aplicar al revés un pedaç binari sense el tros revés a «%s»" +#: apply.c #, c-format msgid "cannot apply binary patch to '%s' without full index line" msgstr "" "no es pot aplicar un pedaç binari a «%s» sense la lÃnia d'Ãndex completa" +#: apply.c #, c-format msgid "" "the patch applies to '%s' (%s), which does not match the current contents." @@ -1013,235 +1231,287 @@ msgstr "" "el pedaç s'aplica a «%s» (%s), el qual no coincideix amb els continguts " "actuals." +#: apply.c #, c-format msgid "the patch applies to an empty '%s' but it is not empty" msgstr "el pedaç s'aplica a un «%s» buit però no és buit" +#: apply.c #, c-format msgid "the necessary postimage %s for '%s' cannot be read" msgstr "no es pot llegir la postimatge %s necessà ria per a «%s»" +#: apply.c #, c-format msgid "binary patch does not apply to '%s'" msgstr "el pedaç binari no s'aplica a «%s»" +#: apply.c #, c-format msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" msgstr "" "el pedaç binari a «%s» crea un resultat incorrecte (s'esperava %s, s'ha " "rebut %s)" +#: apply.c #, c-format msgid "patch failed: %s:%ld" msgstr "el pedaç ha fallat: %s:%ld" +#: apply.c builtin/mv.c #, c-format msgid "cannot checkout %s" msgstr "no es pot agafar %s" +#: apply.c midx.c pack-mtimes.c pack-revindex.c setup.c #, c-format msgid "failed to read %s" msgstr "s'ha produït un error en llegir %s" +#: apply.c #, c-format msgid "reading from '%s' beyond a symbolic link" msgstr "s'està llegint de «%s» més enllà d'un enllaç simbòlic" +#: apply.c #, c-format msgid "path %s has been renamed/deleted" msgstr "el camà %s s'ha canviat de nom / s'ha suprimit" +#: apply.c #, c-format msgid "%s: does not exist in index" msgstr "%s: no existeix en l'Ãndex" +#: apply.c #, c-format msgid "%s: does not match index" msgstr "%s: no coincideix amb l'Ãndex" +#: apply.c msgid "repository lacks the necessary blob to perform 3-way merge." msgstr "" "al repositori li manca el blob necessari per a fer a una fusió de 3 vies." +#: apply.c #, c-format msgid "Performing three-way merge...\n" msgstr "S'està fent una fusió de 3 vies...\n" +#: apply.c #, c-format msgid "cannot read the current contents of '%s'" msgstr "no es poden llegir els continguts actuals de «%s»" +#: apply.c #, c-format msgid "Failed to perform three-way merge...\n" msgstr "S'ha produït un error en fer una fusió de tres vies...\n" +#: apply.c #, c-format msgid "Applied patch to '%s' with conflicts.\n" msgstr "S'ha aplicat el pedaç a «%s» amb conflictes.\n" +#: apply.c #, c-format msgid "Applied patch to '%s' cleanly.\n" msgstr "S'ha aplicat el pedaç a «%s» netament.\n" +#: apply.c #, c-format msgid "Falling back to direct application...\n" msgstr "S'està usant alternativament l'aplicació directa...\n" +#: apply.c msgid "removal patch leaves file contents" msgstr "el pedaç d'eliminació deixa els continguts dels fitxers" +#: apply.c #, c-format msgid "%s: wrong type" msgstr "%s: tipus erroni" +#: apply.c #, c-format msgid "%s has type %o, expected %o" msgstr "%s és del tipus %o, s'esperava %o" +#: apply.c read-cache.c #, c-format msgid "invalid path '%s'" msgstr "camà no và lid: «%s»" +#: apply.c #, c-format msgid "%s: already exists in index" msgstr "%s: ja existeix en l'Ãndex" +#: apply.c #, c-format msgid "%s: already exists in working directory" msgstr "%s: ja existeix en el directori de treball" +#: apply.c #, c-format msgid "new mode (%o) of %s does not match old mode (%o)" msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o)" +#: apply.c #, c-format msgid "new mode (%o) of %s does not match old mode (%o) of %s" msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o) de %s" +#: apply.c #, c-format msgid "affected file '%s' is beyond a symbolic link" msgstr "el fitxer afectat «%s» és més enllà d'un enllaç simbòlic" +#: apply.c #, c-format msgid "%s: patch does not apply" msgstr "%s: el pedaç no s'aplica" +#: apply.c #, c-format msgid "Checking patch %s..." msgstr "S'està comprovant el pedaç %s..." +#: apply.c #, c-format msgid "sha1 information is lacking or useless for submodule %s" msgstr "falta la informació sha1 o és inútil per al submòdul %s" +#: apply.c #, c-format msgid "mode change for %s, which is not in current HEAD" msgstr "canvi de mode per a %s, el qual no està en la HEAD actual" +#: apply.c #, c-format msgid "sha1 information is lacking or useless (%s)." msgstr "falta informació sha1 o és inútil (%s)." +#: apply.c #, c-format msgid "could not add %s to temporary index" msgstr "no s'ha pogut afegir %s a l'Ãndex temporal" +#: apply.c #, c-format msgid "could not write temporary index to %s" msgstr "no s'ha pogut escriure l'Ãndex temporal a %s" +#: apply.c #, c-format msgid "unable to remove %s from index" msgstr "no s'ha pogut eliminar %s de l'Ãndex" +#: apply.c #, c-format msgid "corrupt patch for submodule %s" msgstr "pedaç malmès per al submòdul %s" +#: apply.c #, c-format msgid "unable to stat newly created file '%s'" msgstr "no s'ha pogut fer stat al fitxer novament creat «%s»" +#: apply.c #, c-format msgid "unable to create backing store for newly created file %s" msgstr "" "no s'ha pogut crear un magatzem de suport per al fitxer novament creat %s" +#: apply.c #, c-format msgid "unable to add cache entry for %s" msgstr "no s'ha pogut afegir una entrada de cau per a %s" +#: apply.c builtin/bisect.c builtin/gc.c #, c-format msgid "failed to write to '%s'" msgstr "no s'ha pogut escriure a «%s»" +#: apply.c #, c-format msgid "closing file '%s'" msgstr "s'està tancant el fitxer «%s»" +#: apply.c #, c-format msgid "unable to write file '%s' mode %o" msgstr "no s'ha pogut escriure el fitxer «%s» mode %o" +#: apply.c #, c-format msgid "Applied patch %s cleanly." msgstr "El pedaç %s s'ha aplicat netament." +#: apply.c msgid "internal error" msgstr "error intern" +#: apply.c #, c-format msgid "Applying patch %%s with %d reject..." msgid_plural "Applying patch %%s with %d rejects..." msgstr[0] "S'està aplicant el pedaç %%s amb %d rebuig..." msgstr[1] "S'està aplicant el pedaç %%s amb %d rebutjos..." -#, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "s'està truncant el nom del fitxer .rej a %.*s.rej" - +#: apply.c #, c-format msgid "cannot open %s" msgstr "no es pot obrir %s" +#: apply.c rerere.c #, c-format msgid "cannot unlink '%s'" msgstr "no es pot fer «unlink» de «%s»" +#: apply.c #, c-format msgid "Hunk #%d applied cleanly." msgstr "El tros #%d s'ha aplicat netament." +#: apply.c #, c-format msgid "Rejected hunk #%d." msgstr "S'ha rebutjat el tros #%d." +#: apply.c #, c-format msgid "Skipped patch '%s'." msgstr "S'ha omès el pedaç «%s»." +#: apply.c msgid "No valid patches in input (allow with \"--allow-empty\")" msgstr "No hi ha pedaços và lids a l'entrada (permeteu-los amb «--allow-empty»)" +#: apply.c t/helper/test-cache-tree.c msgid "unable to read index file" msgstr "no es pot llegir el fitxer d'Ãndex" +#: apply.c #, c-format msgid "can't open patch '%s': %s" msgstr "no es pot obrir el pedaç «%s»: %s" +#: apply.c #, c-format msgid "squelched %d whitespace error" msgid_plural "squelched %d whitespace errors" msgstr[0] "s'ha silenciat %d error d'espai en blanc" msgstr[1] "s'han silenciat %d errors d'espai en blanc" +#: apply.c #, c-format msgid "%d line adds whitespace errors." msgid_plural "%d lines add whitespace errors." msgstr[0] "%d lÃnia afegeix errors d'espai en blanc." msgstr[1] "%d lÃnies afegeixen errors d'espai en blanc." +#: apply.c #, c-format msgid "%d line applied after fixing whitespace errors." msgid_plural "%d lines applied after fixing whitespace errors." @@ -1250,287 +1520,398 @@ msgstr[0] "" msgstr[1] "" "S'han aplicat %d lÃnies després d'arreglar els errors d'espai en blanc." +#: apply.c builtin/mv.c builtin/rm.c msgid "Unable to write new index file" msgstr "No s'ha pogut escriure un fitxer d'Ãndex nou" +#: apply.c msgid "don't apply changes matching the given path" msgstr "no apliquis els canvis que coincideixin amb el camà donat" +#: apply.c msgid "apply changes matching the given path" msgstr "aplica els canvis que coincideixin amb el camà donat" +#: apply.c builtin/am.c msgid "num" msgstr "nombre" +#: apply.c msgid "remove <num> leading slashes from traditional diff paths" msgstr "" "elimina <nombre> barres obliqües inicials dels camins de diferència " "tradicionals" +#: apply.c msgid "ignore additions made by the patch" msgstr "ignora afegiments fets pel pedaç" +#: apply.c msgid "instead of applying the patch, output diffstat for the input" msgstr "" "en lloc d'aplicar el pedaç, emet les estadÃstiques de diferència de l'entrada" +#: apply.c msgid "show number of added and deleted lines in decimal notation" msgstr "mostra el nombre de lÃnies afegides i suprimides en notació decimal" +#: apply.c msgid "instead of applying the patch, output a summary for the input" msgstr "en lloc d'aplicar el pedaç, emet un resum de l'entrada" +#: apply.c msgid "instead of applying the patch, see if the patch is applicable" msgstr "en lloc d'aplicar el pedaç, determina si el pedaç és aplicable" +#: apply.c msgid "make sure the patch is applicable to the current index" msgstr "assegura que el pedaç sigui aplicable a l'Ãndex actual" +#: apply.c msgid "mark new files with `git add --intent-to-add`" msgstr "marca els fitxers nous amb «git add --intent-to-add»" +#: apply.c msgid "apply a patch without touching the working tree" msgstr "aplica un pedaç sense tocar l'arbre de treball" +#: apply.c msgid "accept a patch that touches outside the working area" msgstr "accepta un pedaç que toqui fora de l'à rea de treball" +#: apply.c msgid "also apply the patch (use with --stat/--summary/--check)" msgstr "aplica el pedaç també (useu amb --stat/--summary/--check)" +#: apply.c msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "" "intenta una fusió de tres vies, si falla intenta llavors un pedaç normal" +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "en conflictes, usa la nostra versió" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "en conflictes, usa la seva versió" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "en conflictes, usa una versió d'unió" + +#: apply.c msgid "build a temporary index based on embedded index information" msgstr "construeix un Ãndex temporal basat en la informació d'Ãndex incrustada" +#: apply.c builtin/checkout-index.c msgid "paths are separated with NUL character" msgstr "els camins se separen amb el carà cter NUL" +#: apply.c msgid "ensure at least <n> lines of context match" msgstr "assegura't que almenys <n> lÃnies de context coincideixin" +#: apply.c builtin/am.c builtin/interpret-trailers.c builtin/pack-objects.c +#: builtin/rebase.c msgid "action" msgstr "acció" +#: apply.c msgid "detect new or modified lines that have whitespace errors" msgstr "" "detecta les lÃnies noves o modificades que tinguin errors d'espai en blanc" +#: apply.c msgid "ignore changes in whitespace when finding context" msgstr "ignora els canvis d'espai en blanc en cercar context" +#: apply.c msgid "apply the patch in reverse" msgstr "aplica el pedaç al revés" +#: apply.c msgid "don't expect at least one line of context" msgstr "no esperis almenys una lÃnia de context" +#: apply.c msgid "leave the rejected hunks in corresponding *.rej files" msgstr "deixa els trossos rebutjats en fitxers *.rej corresponents" +#: apply.c msgid "allow overlapping hunks" msgstr "permet trossos superposats" +#: apply.c msgid "tolerate incorrectly detected missing new-line at the end of file" msgstr "tolera una lÃnia nova incorrectament detectada al final del fitxer" +#: apply.c msgid "do not trust the line counts in the hunk headers" msgstr "no confiïs en els recomptes de lÃnia en les capçaleres dels trossos" +#: apply.c builtin/am.c msgid "root" msgstr "arrel" +#: apply.c msgid "prepend <root> to all filenames" msgstr "anteposa <arrel> a tots els noms de fitxer" +#: apply.c msgid "don't return error for empty patches" msgstr "no retornis l'error per als pedaços buits" +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs, i --union requereixen --3way" + +#: archive-tar.c archive-zip.c #, c-format msgid "cannot stream blob %s" msgstr "no es pot transmetre el blob %s" +#: archive-tar.c archive-zip.c #, c-format msgid "unsupported file mode: 0%o (SHA1: %s)" msgstr "mode de fitxer no compatible: 0%o (SHA1: %s)" +#: archive-tar.c archive-zip.c builtin/pack-objects.c #, c-format msgid "deflate error (%d)" msgstr "error de deflació (%d)" +#: archive-tar.c #, c-format msgid "unable to start '%s' filter" msgstr "no s'ha pogut iniciar el filtre «%s»" +#: archive-tar.c msgid "unable to redirect descriptor" msgstr "no s'ha pogut redirigir el descriptor" +#: archive-tar.c #, c-format msgid "'%s' filter reported error" msgstr "«%s» error reportat pel filtre" +#: archive-zip.c #, c-format msgid "path is not valid UTF-8: %s" msgstr "el camà no és và lid en UTF-8: %s" +#: archive-zip.c #, c-format msgid "path too long (%d chars, SHA1: %s): %s" msgstr "el camà és massa llarg (%d carà cters, SHA1: %s): %s" +#: archive-zip.c #, c-format msgid "timestamp too large for this system: %<PRIuMAX>" msgstr "marca de temps massa gran per a aquest sistema: %<PRIuMAX>" +#: archive.c msgid "git archive [<options>] <tree-ish> [<path>...]" msgstr "git archive [<opcions>] <arbre> [<camÃ>...]" +#: archive.c msgid "" "git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]" msgstr "" "git archive --remote <repositori> [--exec <ordre>] [<opcions>] <arbre> " "[<camÃ>...]" +#: archive.c msgid "git archive --remote <repo> [--exec <cmd>] --list" msgstr "git archive --remote <repositori> [--exec <ordre>] --list" +#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c #, c-format msgid "cannot read '%s'" msgstr "no es pot llegir «%s»" +#: archive.c #, c-format msgid "pathspec '%s' matches files outside the current directory" msgstr "" "l'especificació de camà «%s» coincideix amb fitxers fora del directori actual" +#: archive.c builtin/add.c builtin/rm.c #, c-format msgid "pathspec '%s' did not match any files" msgstr "l'especificació de camà «%s» no ha coincidit amb cap fitxer" +#: archive.c #, c-format msgid "no such ref: %.*s" msgstr "no existeix la referència: %.*s" +#: archive.c #, c-format msgid "not a valid object name: %s" msgstr "no és un nom d'objecte và lid: %s" +#: archive.c t/helper/test-cache-tree.c #, c-format msgid "not a tree object: %s" msgstr "no és un objecte d'arbre: %s" +#: archive.c +#, c-format +msgid "failed to unpack tree object %s" +msgstr "s'ha produït un error en desempaquetar l'objecte d'arbre %s" + +#: archive.c #, c-format msgid "File not found: %s" msgstr "Fitxer no trobat: %s" +#: archive.c #, c-format msgid "Not a regular file: %s" msgstr "No és un fitxer normal: %s" +#: archive.c #, c-format msgid "unclosed quote: '%s'" msgstr "cometes no tancades: «%s»" +#: archive.c #, c-format msgid "missing colon: '%s'" msgstr "falten els dos punts: «%s»" +#: archive.c #, c-format msgid "empty file name: '%s'" msgstr "nom de fitxer buit: «%s»" +#: archive.c msgid "fmt" msgstr "format" +#: archive.c msgid "archive format" msgstr "format d'arxiu" +#: archive.c builtin/log.c parse-options.h msgid "prefix" msgstr "prefix" +#: archive.c msgid "prepend prefix to each pathname in the archive" msgstr "anteposa el prefix a cada nom de camà en l'arxiu" +#: archive.c builtin/blame.c builtin/commit-tree.c builtin/config.c +#: builtin/fast-export.c builtin/gc.c builtin/grep.c builtin/hash-object.c +#: builtin/ls-files.c builtin/notes.c builtin/read-tree.c parse-options.h msgid "file" msgstr "fitxer" +#: archive.c msgid "add untracked file to archive" msgstr "inclou els fitxers no seguits a l'arxiu" +#: archive.c msgid "path:content" msgstr "camÃ: contingut" +#: archive.c builtin/archive.c msgid "write the archive to this file" msgstr "escriu l'arxiu a aquest fitxer" +#: archive.c msgid "read .gitattributes in working directory" msgstr "llegeix .gitattributes en el directori de treball" +#: archive.c msgid "report archived files on stderr" msgstr "informa de fitxers arxivats en stderr" +#: archive.c builtin/clone.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c msgid "time" msgstr "data" +#: archive.c msgid "set modification time of archive entries" msgstr "estableix l'hora de modificació de les entrades de l'arxiu" +#: archive.c msgid "set compression level" msgstr "estableix el nivell de compressió" +#: archive.c msgid "list supported archive formats" msgstr "llista els formats d'arxiu admesos" +#: archive.c builtin/archive.c builtin/clone.c builtin/submodule--helper.c msgid "repo" msgstr "repositori" +#: archive.c builtin/archive.c msgid "retrieve the archive from remote repository <repo>" msgstr "recupera l'arxiu del repositori remot <repositori>" +#: archive.c builtin/archive.c builtin/difftool.c builtin/notes.c msgid "command" msgstr "ordre" +#: archive.c builtin/archive.c msgid "path to the remote git-upload-archive command" msgstr "camà a l'ordre git-upload-archive remota" +#: archive.c msgid "Unexpected option --remote" msgstr "Opció inesperada --remote" +#: archive.c builtin/add.c builtin/checkout.c builtin/clone.c builtin/commit.c +#: builtin/fast-export.c builtin/index-pack.c builtin/log.c builtin/reset.c +#: builtin/rm.c builtin/stash.c builtin/worktree.c fetch-pack.c http-fetch.c +#: revision.c #, c-format msgid "the option '%s' requires '%s'" msgstr "l'opció «%s» requereix «%s»" +#: archive.c msgid "Unexpected option --output" msgstr "Opció inesperada --output" +#: archive.c t/unit-tests/unit-test.c #, c-format msgid "extra command line parameter '%s'" msgstr "parà metre extra de la lÃnia d'ordres «%s»" +#: archive.c #, c-format msgid "Unknown archive format '%s'" msgstr "Format d'arxiu desconegut «%s»" +#: archive.c #, c-format msgid "Argument not supported for format '%s': -%d" msgstr "Argument no admès per al format «%s»: -%d" +#: attr.c #, c-format msgid "%.*s is not a valid attribute name" msgstr "%.*s no és un nom d'atribut và lid" +#: attr.c msgid "unable to add additional attribute" msgstr "no s'ha pogut afegir l'atribut addicional" +#: attr.c #, c-format msgid "ignoring overly long attributes line %d" msgstr "s'ignorarà la lÃnia d'atributs massa llarga %d" +#: attr.c #, c-format msgid "%s not allowed: %s:%d" msgstr "%s no està permès: %s:%d" +#: attr.c msgid "" "Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." @@ -1538,41 +1919,56 @@ msgstr "" "Els patrons negatius s'ignoren en els atributs de git\n" "Useu «\\!» per exclamació capdavantera literal." +#: attr.c #, c-format msgid "cannot fstat gitattributes file '%s'" msgstr "no es pot fer fstat gitattributes al fitxer «%s»" +#: attr.c #, c-format msgid "ignoring overly large gitattributes file '%s'" msgstr "s'ignorarà el fitxer «%s» gitattributes per a ser massa gran" +#: attr.c #, c-format msgid "ignoring overly large gitattributes blob '%s'" msgstr "s'ignorarà el blob «%s» gitattributes per a ser massa gran" +#: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "no es pot usar --attr-source o GIT_ATTR_SOURCE sense repository" + +#: attr.c msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "--attr-source incorrecte o GIT_ATTR_SOURCE" +#: attr.c read-cache.c #, c-format msgid "unable to stat '%s'" msgstr "no s'ha pogut fer «stat» a «%s»" +#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c #, c-format msgid "unable to read %s" msgstr "no s'ha pogut llegir %s" +#: bisect.c #, c-format msgid "Badly quoted content in file '%s': %s" msgstr "Comentari amb cometes errònies en el fitxer «%s»: %s" +#: bisect.c #, c-format msgid "We cannot bisect more!\n" msgstr "No podem bisecar més!\n" +#: bisect.c #, c-format msgid "Not a valid commit name %s" msgstr "No és un nom de comissió và lid %s" +#: bisect.c #, c-format msgid "" "The merge base %s is bad.\n" @@ -1581,6 +1977,7 @@ msgstr "" "La base de fusió %s és errònia.\n" "Això vol dir que el defecte s'ha arreglat entre %s i [%s].\n" +#: bisect.c #, c-format msgid "" "The merge base %s is new.\n" @@ -1589,6 +1986,7 @@ msgstr "" "La base de fusió %s és nova.\n" "La propietat s'ha canviat entre %s i [%s].\n" +#: bisect.c #, c-format msgid "" "The merge base %s is %s.\n" @@ -1597,6 +1995,7 @@ msgstr "" "La base de fusió %s és %s.\n" "Això vol dir que la primera comissió «%s» és entre %s i [%s].\n" +#: bisect.c #, c-format msgid "" "Some %s revs are not ancestors of the %s rev.\n" @@ -1607,6 +2006,7 @@ msgstr "" "git bisect no pot funcionar correctament en aquest cas.\n" "Potser heu confós les revisions %s i %s?\n" +#: bisect.c #, c-format msgid "" "the merge base between %s and [%s] must be skipped.\n" @@ -1618,29 +2018,41 @@ msgstr "" "%s.\n" "Continuem de totes maneres." +#: bisect.c #, c-format msgid "Bisecting: a merge base must be tested\n" msgstr "Bisecant: s'ha de provar una base de fusió\n" +#: bisect.c #, c-format msgid "a %s revision is needed" msgstr "es necessita una revisió %s" +#: bisect.c #, c-format msgid "could not create file '%s'" msgstr "no s'ha pogut crear el fitxer «%s»" +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "no s'ha pogut iniciar «show» per a l'objecte «%s»" + +#: bisect.c builtin/merge.c #, c-format msgid "could not read file '%s'" msgstr "no s'ha pogut llegir el fitxer «%s»" +#: bisect.c msgid "reading bisect refs failed" msgstr "la lectura de les referències de bisecció ha fallat" +#: bisect.c #, c-format msgid "%s was both %s and %s\n" msgstr "%s era ambdós %s i %s\n" +#: bisect.c #, c-format msgid "" "No testable commit found.\n" @@ -1649,6 +2061,7 @@ msgstr "" "No s'ha trobat cap comissió comprovable.\n" "Potser heu començat amb parà metres de camà incorrectes?\n" +#: bisect.c #, c-format msgid "(roughly %d step)" msgid_plural "(roughly %d steps)" @@ -1658,36 +2071,46 @@ msgstr[1] "(aproximadament %d passos)" #. TRANSLATORS: the last %s will be replaced with "(roughly %d #. steps)" translation. #. +#: bisect.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] "Bisecant: manca %d revisió a provar després d'aquesta %s\n" msgstr[1] "Bisecant: manquen %d revisions a provar després d'aquesta %s\n" +#: blame.c msgid "--contents and --reverse do not blend well." msgstr "--contents i --reverse no funcionen bé juntes." +#: blame.c msgid "--reverse and --first-parent together require specified latest commit" msgstr "" "--reverse i --first-parent junts requereixen una última comissió especificada" +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c +#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c +#: remote.c sequencer.c submodule.c msgid "revision walk setup failed" msgstr "la configuració del recorregut de revisions ha fallat" +#: blame.c msgid "" "--reverse --first-parent together require range along first-parent chain" msgstr "" "--reverse --first-parent junts requereixen un rang de la cadena de pares " "primers" +#: blame.c #, c-format msgid "no such path %s in %s" msgstr "no hi ha tal camà %s en %s" +#: blame.c #, c-format msgid "cannot read blob %s for path %s" msgstr "no es pot llegir el blob %s per al camà %s" +#: branch.c msgid "" "cannot inherit upstream tracking configuration of multiple refs when " "rebasing is requested" @@ -1695,25 +2118,31 @@ msgstr "" "no es pot heretar la configuració del seguiment de la font de múltiples " "referències quan es demana fer «rebase»" +#: branch.c #, c-format msgid "not setting branch '%s' as its own upstream" msgstr "no s'està establert la branca «%s» com a la seva pròpia font" +#: branch.c #, c-format msgid "branch '%s' set up to track '%s' by rebasing." msgstr "la branca «%s» està configurada per a seguir «%s» fent «rebase»." +#: branch.c #, c-format msgid "branch '%s' set up to track '%s'." msgstr "la branca «%s» està configurada per a seguir «%s»." +#: branch.c #, c-format msgid "branch '%s' set up to track:" msgstr "la branca «%s» està configurada per a seguir:" +#: branch.c msgid "unable to write upstream branch configuration" msgstr "no es pot escriure la configuració de la branca font" +#: branch.c msgid "" "\n" "After fixing the error cause you may try to fix up\n" @@ -1723,18 +2152,21 @@ msgstr "" "Després de corregir la causa de l'error, podeu intentar\n" "corregir la informació de seguiment remot executant:" +#: branch.c #, c-format msgid "asked to inherit tracking from '%s', but no remote is set" msgstr "" "s'ha demanat que hereti el seguiment de «%s», però no s'ha establert cap " "remot" +#: branch.c #, c-format msgid "asked to inherit tracking from '%s', but no merge configuration is set" msgstr "" "s'ha demanat que hereti el seguiment de «%s», però no s'ha establert cap " "configuració de fusionat" +#: branch.c #, c-format msgid "not tracking: ambiguous information for ref '%s'" msgstr "no s'està seguint: informació ambigua per a la referència «%s»" @@ -1750,6 +2182,7 @@ msgstr "no s'està seguint: informació ambigua per a la referència «%s»" #. you'll probably want to swap the "%s" and leading " " space #. around. #. +#: branch.c object-name.c #, c-format msgid " %s\n" msgstr " %s\n" @@ -1757,6 +2190,7 @@ msgstr " %s\n" #. TRANSLATORS: The second argument is a \n-delimited list of #. duplicate refspecs, composed above. #. +#: branch.c #, c-format msgid "" "There are multiple remotes whose fetch refspecs map to the remote\n" @@ -1777,30 +2211,40 @@ msgstr "" "els diferents refspecs remots s'assignen a diferents espais de noms\n" "de seguiment." +#: branch.c #, c-format msgid "'%s' is not a valid branch name" msgstr "«%s» no és un nom de branca và lid" +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "Vegeu `man git check-ref-format`" + +#: branch.c #, c-format msgid "a branch named '%s' already exists" msgstr "ja existeix una branca amb nom «%s»" +#: branch.c #, c-format msgid "cannot force update the branch '%s' used by worktree at '%s'" msgstr "" "no es pot forçar l'actualització de la branca «%s» utilitzada per l'arbre de " "treball a «%s»" +#: branch.c #, c-format msgid "cannot set up tracking information; starting point '%s' is not a branch" msgstr "" "no es pot configurar la informació de seguiment; el punt inicial «%s» no és " "una branca" +#: branch.c #, c-format msgid "the requested upstream branch '%s' does not exist" msgstr "la branca font demanada «%s» no existeix" +#: branch.c msgid "" "\n" "If you are planning on basing your work on an upstream\n" @@ -1821,22 +2265,27 @@ msgstr "" "«git push -u» per a establir la configuració font\n" "mentre pugeu." +#: branch.c builtin/replace.c #, c-format msgid "not a valid object name: '%s'" msgstr "no és un nom d'objecte và lid: «%s»" +#: branch.c #, c-format msgid "ambiguous object name: '%s'" msgstr "nom d'objecte ambigu: «%s»" +#: branch.c #, c-format msgid "not a valid branch point: '%s'" msgstr "no és un punt de ramificació và lid: «%s»" +#: branch.c #, c-format msgid "submodule '%s': unable to find submodule" msgstr "submòdul «%s»: no es pot trobar el submòdul" +#: branch.c #, c-format msgid "" "You may try updating the submodules using 'git checkout --no-recurse-" @@ -1845,105 +2294,131 @@ msgstr "" "Podeu provar d'actualitzar els submòduls utilitzant «git checkout --no-" "recurse-submodules %s && git submodule update --init»" +#: branch.c #, c-format msgid "submodule '%s': cannot create branch '%s'" msgstr "submòdul «%s»: no es pot crear la branca: «%s»" +#: branch.c #, c-format msgid "'%s' is already used by worktree at '%s'" msgstr "«%s» ja s'utilitza en l'arbre de treball a «%s»" +#: builtin/add.c msgid "git add [<options>] [--] <pathspec>..." -msgstr "git add [<opcions>] [--] <especificació-de-camÃ>..." +msgstr "git add [<opcions>] [--] <especificació-camÃ>..." +#: builtin/add.c #, c-format msgid "cannot chmod %cx '%s'" msgstr "no es pot fer chmod %cx «%s»" +#: builtin/add.c msgid "Unstaged changes after refreshing the index:" msgstr "Canvis «unstaged» després d'actualitzar l'Ãndex:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"s'ha eliminat la configuració add.interactive.useBuiltin\n" -"Per a més detalls, vegeu la seva entrada a «git help config»." - +#: builtin/add.c msgid "could not read the index" msgstr "no s'ha pogut llegir l'Ãndex" +#: builtin/add.c msgid "editing patch failed" msgstr "l'edició del pedaç ha fallat" +#: builtin/add.c read-cache.c #, c-format msgid "could not stat '%s'" msgstr "no s'ha pogut fer stat a «%s»" +#: builtin/add.c msgid "empty patch. aborted" msgstr "pedaç buit. interromput" +#: builtin/add.c #, c-format msgid "could not apply '%s'" msgstr "no s'ha pogut aplicar «%s»" +#: builtin/add.c msgid "The following paths are ignored by one of your .gitignore files:\n" msgstr "" "Els camins següents s'ignoren per un dels vostres fitxers .gitignore:\n" +#: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c +#: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c +#: builtin/rm.c builtin/send-pack.c msgid "dry run" msgstr "fes una prova" +#: builtin/add.c builtin/check-ignore.c builtin/commit.c +#: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c +#: builtin/read-tree.c builtin/refs.c msgid "be verbose" msgstr "sigues detallat" +#: builtin/add.c msgid "interactive picking" msgstr "selecció interactiva" +#: builtin/add.c builtin/checkout.c builtin/reset.c msgid "select hunks interactively" msgstr "selecciona els trossos interactivament" +#: builtin/add.c msgid "edit current diff and apply" msgstr "edita la diferència actual i aplica-la" +#: builtin/add.c msgid "allow adding otherwise ignored files" msgstr "permet afegir fitxers que d'altra manera s'ignoren" +#: builtin/add.c msgid "update tracked files" msgstr "actualitza els fitxers seguits" +#: builtin/add.c msgid "renormalize EOL of tracked files (implies -u)" msgstr "torna a normalitzar EOL dels fitxers seguits (implica -u)" +#: builtin/add.c msgid "record only the fact that the path will be added later" msgstr "registra només el fet que el camà s'afegirà més tard" +#: builtin/add.c msgid "add changes from all tracked and untracked files" msgstr "afegeix els canvis de tots els fitxers seguits i no seguits" +#: builtin/add.c msgid "ignore paths removed in the working tree (same as --no-all)" msgstr "" "ignora els camins eliminats en l'arbre de treball (el mateix que --no-all)" +#: builtin/add.c msgid "don't add, only refresh the index" msgstr "no afegeixis, només actualitza l'Ãndex" +#: builtin/add.c msgid "just skip files which cannot be added because of errors" msgstr "només omet els fitxers que no es poden afegir a causa d'errors" +#: builtin/add.c msgid "check if - even missing - files are ignored in dry run" msgstr "" "comprova si els fitxers, fins i tot els absents, s'ignoren en fer una prova" +#: builtin/add.c builtin/mv.c builtin/rm.c msgid "allow updating entries outside of the sparse-checkout cone" msgstr "permet actualitzar les entrades fora del con del «sparse-checkout»" +#: builtin/add.c builtin/update-index.c msgid "override the executable bit of the listed files" msgstr "sobreescriu el bit executable dels fitxers llistats" +#: builtin/add.c msgid "warn when adding an embedded repository" msgstr "avisa'm quan s'afegeixi un repositori incrustat" +#: builtin/add.c #, c-format msgid "" "You've added another git repository inside your current repository.\n" @@ -1974,161 +2449,197 @@ msgstr "" "\n" "Vegeu «git help submodule» per a més informació." +#: builtin/add.c #, c-format msgid "adding embedded git repository: %s" msgstr "s'està afegint un repositori incrustat: %s" -msgid "" -"Use -f if you really want to add them.\n" -"Turn this message off by running\n" -"\"git config advice.addIgnoredFile false\"" -msgstr "" -"Utilitzeu -f si realment voleu afegir-los.\n" -"Desactiveu aquest missatge executant\n" -"«git config advice.addIgnoredFile false»" +#: builtin/add.c +msgid "Use -f if you really want to add them." +msgstr "\"Useu -f si realment voleu afegir-los." +#: builtin/add.c msgid "adding files failed" msgstr "l'afegiment de fitxers ha fallat" +#: builtin/add.c #, c-format msgid "--chmod param '%s' must be either -x or +x" msgstr "el parà metre --chmod «%s» ha de ser o -x o +x" +#: builtin/add.c builtin/checkout.c builtin/commit.c builtin/reset.c +#: builtin/rm.c builtin/stash.c #, c-format msgid "'%s' and pathspec arguments cannot be used together" msgstr "«%s» i l'especificació de camà no es poden usar juntes" +#: builtin/add.c #, c-format msgid "Nothing specified, nothing added.\n" msgstr "No s'ha especificat res, no s'ha afegit res.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Potser voleu dir «git add .»?\n" -"Desactiveu aquest missatge executant\n" -"«git config advice.addEmptyPathspec false»" +#: builtin/add.c +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Que potser volÃeu dir «git add.»?" +#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c +#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c +#: builtin/reset.c builtin/rm.c builtin/submodule--helper.c read-cache.c +#: rerere.c submodule.c msgid "index file corrupt" msgstr "fitxer d'Ãndex malmès" +#: builtin/add.c builtin/am.c builtin/checkout.c builtin/clone.c +#: builtin/commit.c builtin/stash.c merge.c rerere.c msgid "unable to write new index file" msgstr "no s'ha pogut escriure un fitxer d'Ãndex nou" +#: builtin/am.c builtin/mailinfo.c mailinfo.c #, c-format msgid "bad action '%s' for '%s'" msgstr "acció «%s» incorrecta per a «%s»" +#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c +#: ls-refs.c parallel-checkout.c sequencer.c setup.c #, c-format msgid "invalid value for '%s': '%s'" msgstr "valor no và lid per a «%s»: «%s»" +#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c #, c-format msgid "could not read '%s'" msgstr "no s'ha pogut llegir «%s»" +#: builtin/am.c msgid "could not parse author script" msgstr "no s'ha pogut analitzar l'script d'autor" +#: builtin/am.c builtin/replace.c commit.c sequencer.c #, c-format msgid "could not parse %s" msgstr "no s'ha pogut analitzar %s" +#: builtin/am.c #, c-format msgid "'%s' was deleted by the applypatch-msg hook" msgstr "s'ha suprimit «%s» pel lligam applypatch-msg" +#: builtin/am.c #, c-format msgid "Malformed input line: '%s'." msgstr "LÃnia d'entrada mal formada: «%s»." +#: builtin/am.c #, c-format msgid "Failed to copy notes from '%s' to '%s'" msgstr "S'ha produït un error en copiar les notes de «%s» a «%s»" +#: builtin/am.c msgid "fseek failed" msgstr "fseek ha fallat" +#: builtin/am.c builtin/rebase.c sequencer.c wrapper.c #, c-format msgid "could not open '%s' for reading" msgstr "no s'ha pogut obrir «%s» per a lectura" +#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c #, c-format msgid "could not open '%s' for writing" msgstr "no s'ha pogut obrir «%s» per a escriptura" +#: builtin/am.c #, c-format msgid "could not parse patch '%s'" msgstr "no s'ha pogut analitzar el pedaç «%s»" +#: builtin/am.c msgid "Only one StGIT patch series can be applied at once" msgstr "Només una sèrie de pedaços StGIT es pot aplicar a la vegada" +#: builtin/am.c msgid "invalid timestamp" msgstr "marca de temps no và lida" +#: builtin/am.c msgid "invalid Date line" msgstr "lÃnia Date no và lida" +#: builtin/am.c msgid "invalid timezone offset" msgstr "desplaçament del fus horari no và lid" +#: builtin/am.c msgid "Patch format detection failed." msgstr "La detecció de format de pedaç ha fallat." +#: builtin/am.c builtin/clone.c #, c-format msgid "failed to create directory '%s'" msgstr "s'ha produït un error en crear el directori «%s»" +#: builtin/am.c msgid "Failed to split patches." msgstr "S'ha produït un error en dividir els pedaços." +#: builtin/am.c #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Quan hà giu resolt aquest problema, executeu «%s --continue»." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "Quan hà giu resolt aquest problema, executeu «%s --continue».\n" +#: builtin/am.c #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "Si preferiu ometre aquest pedaç, executeu «%s --skip» en lloc d'això." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "" +"Si preferiu ometre aquest pedaç, executeu «%s --skip» en lloc d'això.\n" +#: builtin/am.c #, c-format -msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"." +msgid "" +"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" msgstr "" "Per a enregistrar un pedaç buit com a comissió buida, executeu «%s --allow-" -"empty»." +"empty».\n" +#: builtin/am.c #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." msgstr "" "Per a restaurar la branca original i deixar d'apedaçar, executeu «%s --" "abort»." +#: builtin/am.c msgid "Patch sent with format=flowed; space at the end of lines might be lost." msgstr "" "Pedaç enviat amb format=flowed; es pot perdre l'espai al final de les lÃnies." +#: builtin/am.c #, c-format msgid "missing author line in commit %s" msgstr "manca la lÃnia d'autor en la comissió %s" +#: builtin/am.c #, c-format msgid "invalid ident line: %.*s" msgstr "lÃnia d'identitat no và lida: %.*s" +#: builtin/am.c builtin/checkout.c builtin/clone.c commit-graph.c #, c-format msgid "unable to parse commit %s" msgstr "no s'ha pogut analitzar la comissió %s" +#: builtin/am.c msgid "Repository lacks necessary blobs to fall back on 3-way merge." msgstr "" "Al repositori li manquen els blobs necessaris per a retrocedir a una fusió " "de 3 vies." +#: builtin/am.c msgid "Using index info to reconstruct a base tree..." msgstr "S'està usant la informació d'Ãndex per a reconstruir un arbre base..." +#: builtin/am.c msgid "" "Did you hand edit your patch?\n" "It does not apply to blobs recorded in its index." @@ -2136,25 +2647,32 @@ msgstr "" "Heu editat el vostre pedaç a mà ?\n" "No s'aplica als blobs recordats en el seu Ãndex." +#: builtin/am.c msgid "Falling back to patching base and 3-way merge..." msgstr "S'està retrocedint a apedaçar la base i una fusió de 3 vies..." +#: builtin/am.c msgid "Failed to merge in the changes." msgstr "S'ha produït un error en fusionar els canvis." +#: builtin/am.c builtin/merge.c sequencer.c msgid "git write-tree failed to write a tree" msgstr "git write-tree ha fallat en escriure un arbre" +#: builtin/am.c msgid "applying to an empty history" msgstr "s'està aplicant a una història buida" +#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c msgid "failed to write commit object" msgstr "s'ha produït un error en escriure l'objecte de comissió" +#: builtin/am.c #, c-format msgid "cannot resume: %s does not exist." msgstr "no es pot reprendre: %s no existeix." +#: builtin/am.c msgid "Commit Body is:" msgstr "El cos de la comissió és:" @@ -2162,48 +2680,60 @@ msgstr "El cos de la comissió és:" #. in your translation. The program will only accept English #. input at this point. #. +#: builtin/am.c #, c-format msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " msgstr "" "Voleu aplicar-lo? [y]es/[n]o/[e]dita/[v]isualitza el pedaç/[a]ccepta'ls " "tots: " +#: builtin/am.c builtin/commit.c msgid "unable to write index file" msgstr "no s'ha pogut escriure el fitxer d'Ãndex" +#: builtin/am.c #, c-format msgid "Dirty index: cannot apply patches (dirty: %s)" msgstr "Ãndex brut: no es poden aplicar pedaços (bruts: %s)" +#: builtin/am.c #, c-format msgid "Skipping: %.*s" msgstr "S'està ometent: %.*s" +#: builtin/am.c #, c-format msgid "Creating an empty commit: %.*s" msgstr "S'està creant una comissió buida: %.*s" +#: builtin/am.c msgid "Patch is empty." msgstr "El pedaç està buit." +#: builtin/am.c #, c-format msgid "Applying: %.*s" msgstr "S'està aplicant: %.*s" +#: builtin/am.c msgid "No changes -- Patch already applied." msgstr "Sense canvis -- El pedaç ja s'ha aplicat." +#: builtin/am.c #, c-format msgid "Patch failed at %s %.*s" msgstr "El pedaç ha fallat a %s %.*s" +#: builtin/am.c msgid "Use 'git am --show-current-patch=diff' to see the failed patch" msgstr "" "Useu «git am --show-current-patch=diff» per a veure el pedaç que ha fallat" +#: builtin/am.c msgid "No changes - recorded it as an empty commit." msgstr "No hi ha canvis - enregistrat com una comissió buida." +#: builtin/am.c msgid "" "No changes - did you forget to use 'git add'?\n" "If there is nothing left to stage, chances are that something else\n" @@ -2213,6 +2743,7 @@ msgstr "" "Si no hi ha res per a fer «stage», probablement alguna altra cosa ja ha\n" "introduït els mateixos canvis; potser voleu ometre aquest pedaç." +#: builtin/am.c msgid "" "You still have unmerged paths in your index.\n" "You should 'git add' each file with resolved conflicts to mark them as " @@ -2225,13 +2756,16 @@ msgstr "" "Podeu executar «git rm» en un fitxer per a acceptar «suprimit per ells» pel " "fitxer." +#: builtin/am.c builtin/reset.c #, c-format msgid "Could not parse object '%s'." msgstr "No s'ha pogut analitzar l'objecte «%s»." +#: builtin/am.c msgid "failed to clean index" msgstr "s'ha produït un error en netejar l'Ãndex" +#: builtin/am.c msgid "" "You seem to have moved HEAD since the last 'am' failure.\n" "Not rewinding to ORIG_HEAD" @@ -2239,109 +2773,155 @@ msgstr "" "Sembla que heu mogut HEAD després de l'última fallada de «am».\n" "No s'està rebobinant a ORIG_HEAD" +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c #, c-format msgid "failed to read '%s'" msgstr "s'ha produït un error en llegir «%s»" +#: builtin/am.c msgid "git am [<options>] [(<mbox> | <Maildir>)...]" msgstr "git am [<opcions>] [(<bústia> | <directori-de-correu>)...]" +#: builtin/am.c msgid "git am [<options>] (--continue | --skip | --abort)" msgstr "git am [<opcions>] (--continue | --skip | --abort)" +#: builtin/am.c msgid "run interactively" msgstr "executa interactivament" +#: builtin/am.c msgid "bypass pre-applypatch and applypatch-msg hooks" msgstr "evita els lligams pre-applypatch i applypatch-msg" +#: builtin/am.c msgid "historical option -- no-op" msgstr "opció històrica -- no-op" +#: builtin/am.c msgid "allow fall back on 3way merging if needed" msgstr "permet retrocedir a una fusió de 3 vies si és necessari" +#: builtin/am.c builtin/init-db.c builtin/prune-packed.c builtin/repack.c +#: builtin/stash.c msgid "be quiet" msgstr "silenciós" +#: builtin/am.c msgid "add a Signed-off-by trailer to the commit message" msgstr "afegeix un «trailer» tipus «Signed-off-by» al missatge de comissió" +#: builtin/am.c msgid "recode into utf8 (default)" msgstr "recodifica en utf8 (per defecte)" +#: builtin/am.c msgid "pass -k flag to git-mailinfo" msgstr "passa l'indicador -k a git-mailinfo" +#: builtin/am.c msgid "pass -b flag to git-mailinfo" msgstr "passa l'indicador -b a git-mailinfo" +#: builtin/am.c msgid "pass -m flag to git-mailinfo" msgstr "passa l'indicador -m a git-mailinfo" +#: builtin/am.c msgid "pass --keep-cr flag to git-mailsplit for mbox format" msgstr "passa l'indicador --keep-cr a git-mailsplit per al format mbox" +#: builtin/am.c msgid "strip everything before a scissors line" msgstr "elimina tot abans d'una lÃnia de tisores" +#: builtin/am.c msgid "pass it through git-mailinfo" msgstr "passa-ho a través del git-mailinfo" +#: builtin/am.c msgid "pass it through git-apply" msgstr "passa-ho a través de git-apply" +#: builtin/am.c builtin/commit.c builtin/fmt-merge-msg.c builtin/grep.c +#: builtin/merge.c builtin/pull.c builtin/rebase.c builtin/repack.c +#: builtin/show-branch.c builtin/show-ref.c builtin/tag.c parse-options.h msgid "n" msgstr "n" +#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c +#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c msgid "format" msgstr "format" +#: builtin/am.c msgid "format the patch(es) are in" msgstr "el format en el qual estan els pedaços" +#: builtin/am.c msgid "override error message when patch failure occurs" msgstr "sobreescriu el missatge d'error si falla l'aplicació del pedaç" +#: builtin/am.c msgid "continue applying patches after resolving a conflict" msgstr "segueix aplicant pedaços després de resoldre un conflicte" +#: builtin/am.c msgid "synonyms for --continue" msgstr "sinònims de --continue" +#: builtin/am.c msgid "skip the current patch" msgstr "omet el pedaç actual" +#: builtin/am.c msgid "restore the original branch and abort the patching operation" msgstr "restaura la branca original i interromp l'operació d'apedaçament" +#: builtin/am.c msgid "abort the patching operation but keep HEAD where it is" msgstr "interromp l'operació d'apedaçament però manté HEAD on és" +#: builtin/am.c msgid "show the patch being applied" msgstr "mostra el pedaç que s'està aplicant" +#: builtin/am.c +msgid "try to apply current patch again" +msgstr "intenta aplicar el pedaç actual de nou" + +#: builtin/am.c msgid "record the empty patch as an empty commit" msgstr "registra el pedaç buit com una comissió buida" +#: builtin/am.c msgid "lie about committer date" msgstr "menteix sobre la data del comitent" +#: builtin/am.c msgid "use current timestamp for author date" msgstr "usa la marca de temps actual per a la data d'autor" +#: builtin/am.c builtin/commit-tree.c builtin/commit.c builtin/merge.c +#: builtin/pull.c builtin/rebase.c builtin/revert.c builtin/tag.c msgid "key-id" msgstr "ID de clau" +#: builtin/am.c builtin/rebase.c msgid "GPG-sign commits" msgstr "signa les comissions amb GPG" +#: builtin/am.c msgid "how to handle empty patches" msgstr "com gestionar les comissions buides" +#: builtin/am.c msgid "(internal use for git-rebase)" msgstr "(ús intern per a git-rebase)" +#: builtin/am.c msgid "" "The -b/--binary option has been a no-op for long time, and\n" "it will be removed. Please do not use it anymore." @@ -2349,15 +2929,18 @@ msgstr "" "Fa molt que l'opció -b/--binary no fa res, i\n" "s'eliminarà . No l'useu més." +#: builtin/am.c msgid "failed to read the index" msgstr "s'ha produït un error en llegir l'Ãndex" +#: builtin/am.c #, c-format msgid "previous rebase directory %s still exists but mbox given." msgstr "" "un directori de «rebase» anterior %s encara existeix però s'ha donat una " "bústia." +#: builtin/am.c #, c-format msgid "" "Stray %s directory found.\n" @@ -2366,34 +2949,40 @@ msgstr "" "S'ha trobat un directori %s extraviat.\n" "Useu «git am --abort» per a eliminar-lo." +#: builtin/am.c msgid "Resolve operation not in progress, we are not resuming." msgstr "Una operació de resolució no està en curs; no reprenem." +#: builtin/am.c msgid "interactive mode requires patches on the command line" msgstr "el mode interactiu requereix pedaços a la lÃnia d'ordres" +#: builtin/apply.c msgid "git apply [<options>] [<patch>...]" msgstr "git apply [<opcions>] [<pedaç>...]" +#: builtin/archive.c diagnose.c msgid "could not redirect output" msgstr "no s'ha pogut redirigir la sortida" -msgid "git archive: Remote with no URL" -msgstr "git archive: Remot sense URL" - +#: builtin/archive.c msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: s'esperava ACK/NAK, s'ha rebut un paquet de buidatge" +#: builtin/archive.c #, c-format msgid "git archive: NACK %s" msgstr "git archive: %s NACK" +#: builtin/archive.c msgid "git archive: protocol error" msgstr "git archive: error de protocol" +#: builtin/archive.c msgid "git archive: expected a flush" msgstr "git archive: s'esperava una neteja" +#: builtin/bisect.c msgid "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" @@ -2401,56 +2990,71 @@ msgstr "" "git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" "checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" +#: builtin/bisect.c msgid "git bisect (good|bad) [<rev>...]" -msgstr "git bisect (good|bad) [<rev>...]" +msgstr "git bisect (good|bad) [<revisió>...]" +#: builtin/bisect.c msgid "git bisect skip [(<rev>|<range>)...]" -msgstr "git bisect skip [(<rev>|<range>)...]" +msgstr "git bisect skip [(<revisió>|<rang>)...]" +#: builtin/bisect.c msgid "git bisect reset [<commit>]" msgstr "git bisect reset [<comissió>]" +#: builtin/bisect.c msgid "git bisect replay <logfile>" -msgstr "git bisect replay <logfile>" +msgstr "git bisect replay " +#: builtin/bisect.c msgid "git bisect run <cmd> [<arg>...]" -msgstr "git bisect run <cmd> [<arg>...]" +msgstr "git bisect run <ordre> [<arg>...]" +#: builtin/bisect.c #, c-format msgid "cannot open file '%s' in mode '%s'" msgstr "no es pot obrir el fitxer «%s» en mode «%s»" +#: builtin/bisect.c #, c-format msgid "could not write to file '%s'" msgstr "no s'ha pogut escriure el fitxer «%s»" +#: builtin/bisect.c #, c-format msgid "cannot open file '%s' for reading" msgstr "no es pot obrir «%s» per a lectura" +#: builtin/bisect.c #, c-format msgid "'%s' is not a valid term" msgstr "«%s» no és un terme và lid" +#: builtin/bisect.c #, c-format msgid "can't use the builtin command '%s' as a term" msgstr "no es pot usar l'ordre interna «%s» com a terme" +#: builtin/bisect.c #, c-format msgid "can't change the meaning of the term '%s'" msgstr "no es pot canviar el significat del terme «%s»" +#: builtin/bisect.c msgid "please use two different terms" msgstr "useu dos termes diferents" +#: builtin/bisect.c #, c-format msgid "We are not bisecting.\n" msgstr "No estem bisecant.\n" +#: builtin/bisect.c #, c-format msgid "'%s' is not a valid commit" msgstr "«%s» no és una comissió và lida" +#: builtin/bisect.c #, c-format msgid "" "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." @@ -2458,22 +3062,27 @@ msgstr "" "no s'ha pogut agafar la HEAD original «%s». Proveu «git bisect reset " "<comissió>»." +#: builtin/bisect.c #, c-format msgid "Bad bisect_write argument: %s" msgstr "Argument «bisect_write» incorrecte: %s" +#: builtin/bisect.c #, c-format msgid "couldn't get the oid of the rev '%s'" msgstr "no s'ha pogut obtenir l'oid de la revisió «%s»" +#: builtin/bisect.c #, c-format msgid "couldn't open the file '%s'" msgstr "no s'ha pogut obrir el fitxer «%s»" +#: builtin/bisect.c #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" msgstr "Ordre no và lida: esteu actualment en una bisecció %s/%s" +#: builtin/bisect.c #, c-format msgid "" "You need to give me at least one %s and %s revision.\n" @@ -2482,6 +3091,7 @@ msgstr "" "Heu de donar com a mÃnim un %s i una revisió %s.\n" "Podeu usar «git bisect %s» i «git bisect %s» per a això." +#: builtin/bisect.c #, c-format msgid "" "You need to start by \"git bisect start\".\n" @@ -2492,6 +3102,7 @@ msgstr "" "Heu de donar com a mÃnim un %s i una revisió %s.\n" "Podeu usar «git bisect %s» i «git bisect %s» per a això." +#: builtin/bisect.c #, c-format msgid "bisecting only with a %s commit" msgstr "bisecant amb només una comissió %s" @@ -2500,12 +3111,15 @@ msgstr "bisecant amb només una comissió %s" #. translation. The program will only accept English input #. at this point. #. +#: builtin/bisect.c msgid "Are you sure [Y/n]? " msgstr "N'esteu segur [Y/n]? " +#: builtin/bisect.c msgid "status: waiting for both good and bad commits\n" msgstr "estat: s'estan esperant les comissions bones i dolentes\n" +#: builtin/bisect.c #, c-format msgid "status: waiting for bad commit, %d good commit known\n" msgid_plural "status: waiting for bad commit, %d good commits known\n" @@ -2515,13 +3129,16 @@ msgstr[1] "" "estat: s'està esperant una comissió incorrecta, es coneixen %d comissions " "bones\n" +#: builtin/bisect.c msgid "status: waiting for good commit(s), bad commit known\n" msgstr "" "estat: s'està esperant comissions bones, es coneix una comissió incorrecta\n" +#: builtin/bisect.c msgid "no terms defined" msgstr "cap terme definit" +#: builtin/bisect.c #, c-format msgid "" "Your current terms are %s for the old state\n" @@ -2530,6 +3147,7 @@ msgstr "" "Els termes actuals són %s per a l'estat antic\n" "i %s per al nou estat.\n" +#: builtin/bisect.c #, c-format msgid "" "invalid argument %s for 'git bisect terms'.\n" @@ -2538,39 +3156,45 @@ msgstr "" "argument no và lid %s per a «git bisect terms».\n" "Les opcions admeses són: --term-good|--term-old i --term-bad|--term-new." -msgid "revision walk setup failed\n" -msgstr "la configuració del recorregut de revisions ha fallat\n" - +#: builtin/bisect.c #, c-format msgid "could not open '%s' for appending" msgstr "no s'ha pogut obrir «%s» per a afegir-hi" +#: builtin/bisect.c msgid "'' is not a valid term" msgstr "«%s» no és un terme và lid" +#: builtin/bisect.c #, c-format msgid "unrecognized option: '%s'" msgstr "opció no reconeguda: «%s»" +#: builtin/bisect.c #, c-format msgid "'%s' does not appear to be a valid revision" msgstr "«%s» no sembla ser una revisió và lida" +#: builtin/bisect.c msgid "bad HEAD - I need a HEAD" msgstr "HEAD incorrecte - cal una HEAD" +#: builtin/bisect.c #, c-format msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'." msgstr "" "l'agafament de «%s» ha fallat. Proveu «git bisect start <branca-và lida>»." +#: builtin/bisect.c msgid "bad HEAD - strange symbolic ref" msgstr "HEAD incorrecte - referència simbòlica estranya" +#: builtin/bisect.c #, c-format msgid "invalid ref: '%s'" msgstr "referència no és và lida: «%s»" +#: builtin/bisect.c msgid "You need to start by \"git bisect start\"\n" msgstr "Cal començar per «git bisect start»\n" @@ -2578,215 +3202,278 @@ msgstr "Cal començar per «git bisect start»\n" #. translation. The program will only accept English input #. at this point. #. +#: builtin/bisect.c msgid "Do you want me to do it for you [Y/n]? " msgstr "Voleu que ho faci per vostè [Y/n]? " +#: builtin/bisect.c msgid "Please call `--bisect-state` with at least one argument" msgstr "Executeu «--bisect-state» amb almenys un argument" +#: builtin/bisect.c #, c-format msgid "'git bisect %s' can take only one argument." msgstr "«git bisect %s» només pot acceptar un argument." +#: builtin/bisect.c #, c-format msgid "Bad rev input: %s" msgstr "Entrada amb revisió errònia: %s" +#: builtin/bisect.c #, c-format msgid "Bad rev input (not a commit): %s" msgstr "Entrada de revisió errònia (no és una comissió): %s" +#: builtin/bisect.c msgid "We are not bisecting." msgstr "No estem bisecant." +#: builtin/bisect.c #, c-format msgid "'%s'?? what are you talking about?" msgstr "«%s»? Què voleu dir?" +#: builtin/bisect.c #, c-format msgid "cannot read file '%s' for replaying" msgstr "no es pot llegir «%s» per a reproducció" +#: builtin/bisect.c #, c-format msgid "running %s\n" msgstr "s'està executant %s\n" +#: builtin/bisect.c msgid "bisect run failed: no command provided." msgstr "ha fallat l'execució de bisect: no s'ha proporcionat cap ordre." +#: builtin/bisect.c #, c-format msgid "unable to verify %s on good revision" msgstr "no s'ha pogut verificar «%s» en una bona revisió" +#: builtin/bisect.c #, c-format msgid "bogus exit code %d for good revision" msgstr "codi d'error de sortida %d per a una bona revisió" +#: builtin/bisect.c #, c-format msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" msgstr "" "l'execució de la de bisecció ha fallat: codi de sortida %d de %s és < 0 o >= " "128" +#: builtin/bisect.c #, c-format msgid "cannot open file '%s' for writing" msgstr "no es pot obrir «%s» per a escriptura" +#: builtin/bisect.c msgid "bisect run cannot continue any more" msgstr "l'execució de la bisecció no pot continuar més" +#: builtin/bisect.c msgid "bisect run success" msgstr "execució de bisecció amb èxit" +#: builtin/bisect.c msgid "bisect found first bad commit" msgstr "la bisecció ha trobat una primera comissió errònia" +#: builtin/bisect.c #, c-format msgid "bisect run failed: 'git bisect %s' exited with error code %d" msgstr "" "ha fallat l'execució del bisect: «git bisect %s» ha sortit amb el codi " "d'error %d" +#: builtin/bisect.c #, c-format msgid "'%s' requires either no argument or a commit" msgstr "«%s» no requereix cap argument ni comissió" +#: builtin/bisect.c #, c-format msgid "'%s' requires 0 or 1 argument" msgstr "%s requereix 0 o 1 arguments" +#: builtin/bisect.c #, c-format msgid "'%s' requires 0 arguments" msgstr "«%s» requereix 0 arguments" +#: builtin/bisect.c msgid "no logfile given" msgstr "no s'ha donat cap fitxer de registre" +#: builtin/bisect.c #, c-format msgid "'%s' failed: no command provided." msgstr "«%s» ha fallat: no s'ha proporcionat cap ordre." +#: builtin/bisect.c msgid "need a command" msgstr "cal una subordre" +#: builtin/bisect.c builtin/cat-file.c #, c-format msgid "unknown command: '%s'" msgstr "ordre desconeguda: «%s»" +#: builtin/blame.c msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>" -msgstr "git blame [<opcions>] [<opcions-de-revisió>] [<revisió>] [--] fitxer" +msgstr "git blame [<opcions>] [<opcions-revisió>] [<revisió>] [--] fitxer" +#: builtin/blame.c msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>" -msgstr "git annotate [<opcions>] [<rev-opts>] [<rev>] [--] <fitxer>" +msgstr "git annotate [<opcions>] [<opcions-revisió>] [<rev>] [--] <fitxer>" +#: builtin/blame.c msgid "<rev-opts> are documented in git-rev-list(1)" -msgstr "es documenten les <opcions-de-revisió> en git-rev-list(1)" +msgstr "es documenten les <opcions-revisió> en git-rev-list(1)" +#: builtin/blame.c #, c-format msgid "expecting a color: %s" msgstr "s'esperava un color: %s" +#: builtin/blame.c msgid "must end with a color" msgstr "ha d'acabar amb un color" +#: builtin/blame.c #, c-format msgid "cannot find revision %s to ignore" msgstr "no s'ha pogut trobar la revisió %s a ignorar" +#: builtin/blame.c msgid "show blame entries as we find them, incrementally" msgstr "mostra les entrades «blame» mentre les trobem, incrementalment" +#: builtin/blame.c msgid "do not show object names of boundary commits (Default: off)" msgstr "" "no mostris els noms d'objectes de les comissions de frontera (per defecte: " "desactivat)" +#: builtin/blame.c msgid "do not treat root commits as boundaries (Default: off)" msgstr "" "no tractis les comissions arrel com de frontera (per defecte: desactivat)" +#: builtin/blame.c msgid "show work cost statistics" msgstr "mostra les estadÃstiques del cost de treball" +#: builtin/blame.c builtin/checkout.c builtin/clone.c builtin/commit-graph.c +#: builtin/fetch.c builtin/merge.c builtin/multi-pack-index.c builtin/pull.c +#: builtin/push.c builtin/remote.c builtin/send-pack.c msgid "force progress reporting" msgstr "força l'informe de progrés" +#: builtin/blame.c msgid "show output score for blame entries" msgstr "mostra la puntuació de sortida de les entrades «blame»" +#: builtin/blame.c msgid "show original filename (Default: auto)" msgstr "mostra el nom de fitxer original (per defecte: automà tic)" +#: builtin/blame.c msgid "show original linenumber (Default: off)" msgstr "mostra el número de lÃnia original (per defecte: desactivat)" +#: builtin/blame.c msgid "show in a format designed for machine consumption" msgstr "presenta en un format dissenyat per a ser consumit per una mà quina" +#: builtin/blame.c msgid "show porcelain format with per-line commit information" msgstr "mostra en format de porcellana amb informació de comissió per lÃnia" +#: builtin/blame.c msgid "use the same output mode as git-annotate (Default: off)" msgstr "" "usa el mateix mode de sortida que git-annotate (per defecte: desactivat)" +#: builtin/blame.c msgid "show raw timestamp (Default: off)" msgstr "mostra la marca de temps en cru (per defecte: desactivat)" +#: builtin/blame.c msgid "show long commit SHA1 (Default: off)" msgstr "mostra l'SHA1 de la comissió en format llarg (per defecte: desactivat)" +#: builtin/blame.c msgid "suppress author name and timestamp (Default: off)" msgstr "omet el nom d'autor i la marca de temps (per defecte: desactivat)" +#: builtin/blame.c msgid "show author email instead of name (Default: off)" msgstr "" "mostra el correu electrònic de l'autor en comptes del nom (per defecte: " "desactivat)" +#: builtin/blame.c msgid "ignore whitespace differences" msgstr "ignora les diferències d'espai en blanc" +#: builtin/blame.c builtin/log.c msgid "rev" msgstr "rev" +#: builtin/blame.c msgid "ignore <rev> when blaming" -msgstr "ignora <rev> en fer «blame»" +msgstr "ignora ñ- en fer «blame»" +#: builtin/blame.c msgid "ignore revisions from <file>" msgstr "ignora les revisions de <fitxer>" +#: builtin/blame.c msgid "color redundant metadata from previous line differently" msgstr "" "acoloreix les metadades redundants de la lÃnia anterior de manera diferent" +#: builtin/blame.c msgid "color lines by age" msgstr "acoloreix les lÃnies per antiguitat" +#: builtin/blame.c msgid "spend extra cycles to find better match" msgstr "gasta cicles extres per a trobar una coincidència millor" +#: builtin/blame.c msgid "use revisions from <file> instead of calling git-rev-list" msgstr "usa les revisions de <fitxer> en lloc d'invocar git-rev-list" +#: builtin/blame.c msgid "use <file>'s contents as the final image" msgstr "usa els continguts de <fitxer> com a la imatge final" +#: builtin/blame.c msgid "score" msgstr "puntuació" +#: builtin/blame.c msgid "find line copies within and across files" msgstr "troba còpies de lÃnia dins i a través dels fitxers" +#: builtin/blame.c msgid "find line movements within and across files" msgstr "troba moviments de lÃnia dins i a través dels fitxers" +#: builtin/blame.c msgid "range" msgstr "rang" +#: builtin/blame.c msgid "process only line range <start>,<end> or function :<funcname>" -msgstr "processa només el rang <start>,<end> o la funció :<funcname>" +msgstr "processa només el rang <inici>,<final> o la funció :<nom-funció>" +#: builtin/blame.c msgid "--progress can't be used with --incremental or porcelain formats" msgstr "" "no es pot usar --progress amb els formats --incremental o de porcellana" @@ -2799,21 +3486,26 @@ msgstr "" #. your language may need more or fewer display #. columns. #. +#: builtin/blame.c msgid "4 years, 11 months ago" msgstr "fa 4 anys i 11 mesos" +#: builtin/blame.c #, c-format msgid "file %s has only %lu line" msgid_plural "file %s has only %lu lines" msgstr[0] "el fitxer %s té només %lu lÃnia" msgstr[1] "el fitxer %s té només %lu lÃnies" +#: builtin/blame.c msgid "Blaming lines" msgstr "S'està fent un «blame»" +#: builtin/branch.c msgid "git branch [<options>] [-r | -a] [--merged] [--no-merged]" msgstr "git branch [<opcions>] [-r | -a] [--merged | --no-merged]" +#: builtin/branch.c msgid "" "git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-" "point>]" @@ -2821,24 +3513,31 @@ msgstr "" "git branch [<opcions>] [-f] [--recurse-submodules] <branch-name> [<start-" "point>]" +#: builtin/branch.c msgid "git branch [<options>] [-l] [<pattern>...]" msgstr "git branch [<opcions>] [-l] [<patró>...]" +#: builtin/branch.c msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..." msgstr "git branch [<opcions>] [-r] (-d | -D) <nom-de-branca>..." +#: builtin/branch.c msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>" msgstr "git branch [<opcions>] (-m | -M) [<branca-antiga>] <branca-nova>" +#: builtin/branch.c msgid "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>" msgstr "git branch [<opcions>] (-c | -C) [<branca-antiga>] <branca-nova>" +#: builtin/branch.c msgid "git branch [<options>] [-r | -a] [--points-at]" msgstr "git branch [<opcions>] [-r | -a] [--points-at]" +#: builtin/branch.c msgid "git branch [<options>] [-r | -a] [--format]" msgstr "git branch [<opcions>] [-r | -a] [--format]" +#: builtin/branch.c #, c-format msgid "" "deleting branch '%s' that has been merged to\n" @@ -2847,6 +3546,7 @@ msgstr "" "s'està suprimint la branca «%s» que s'ha fusionat a\n" " «%s», però encara no s'ha fusionat a HEAD" +#: builtin/branch.c #, c-format msgid "" "not deleting branch '%s' that is not yet merged to\n" @@ -2855,33 +3555,41 @@ msgstr "" "no s'està suprimint la branca «%s» que encara no s'ha fusionat a\n" " «%s», encara que s'hagi fusionat a HEAD" +#: builtin/branch.c #, c-format msgid "couldn't look up commit object for '%s'" msgstr "no s'ha pogut cercar l'objecte de comissió per a «%s»" +#: builtin/branch.c #, c-format msgid "the branch '%s' is not fully merged" msgstr "la branca «%s» no està completament fusionada" +#: builtin/branch.c #, c-format msgid "If you are sure you want to delete it, run 'git branch -D %s'" msgstr "Si esteu segur que voleu suprimir-la, executeu «git branch -D %s»" +#: builtin/branch.c msgid "update of config-file failed" msgstr "ha fallat l'actualització del fitxer de configuració" +#: builtin/branch.c msgid "cannot use -a with -d" msgstr "no es pot usar -a amb -d" +#: builtin/branch.c #, c-format msgid "cannot delete branch '%s' used by worktree at '%s'" msgstr "" "no es pot suprimir la branca «%s» utilitzada per l'arbre de treball a «%s»" +#: builtin/branch.c #, c-format msgid "remote-tracking branch '%s' not found" msgstr "no s'ha trobat la branca de seguiment remot «%s»" +#: builtin/branch.c #, c-format msgid "" "branch '%s' not found.\n" @@ -2890,198 +3598,257 @@ msgstr "" "no s'ha trobat la branca «%s».\n" "Us heu oblidat de --remote?" +#: builtin/branch.c #, c-format msgid "branch '%s' not found" msgstr "no s'ha trobat la branca «%s»" +#: builtin/branch.c #, c-format msgid "Deleted remote-tracking branch %s (was %s).\n" msgstr "S'ha suprimit la branca amb seguiment remot %s (era %s).\n" +#: builtin/branch.c #, c-format msgid "Deleted branch %s (was %s).\n" msgstr "S'ha suprimit la branca %s (era %s).\n" +#: builtin/branch.c builtin/tag.c msgid "unable to parse format string" msgstr "no s'ha pogut analitzar la cadena de format" +#: builtin/branch.c msgid "could not resolve HEAD" msgstr "no s'ha pogut resoldre HEAD" +#: builtin/branch.c #, c-format msgid "HEAD (%s) points outside of refs/heads/" msgstr "HEAD (%s) apunta fora de refs/heads/" +#: builtin/branch.c #, c-format msgid "branch %s is being rebased at %s" msgstr "a la branca %s se li està fent a «rebase» a %s" +#: builtin/branch.c #, c-format msgid "branch %s is being bisected at %s" msgstr "la branca %s s'està bisecant a %s" +#: builtin/branch.c #, c-format msgid "HEAD of working tree %s is not updated" msgstr "HEAD de l'arbre de treball %s no està actualitzat" +#: builtin/branch.c #, c-format msgid "invalid branch name: '%s'" msgstr "el nom de la branca no és và lid: «%s»" +#: builtin/branch.c #, c-format msgid "no commit on branch '%s' yet" msgstr "encara no hi ha cap comissió a la branca «%s»" +#: builtin/branch.c #, c-format msgid "no branch named '%s'" msgstr "no hi ha cap branca anomenada «%s»" +#: builtin/branch.c msgid "branch rename failed" msgstr "ha fallat el canvi de nom de la branca" +#: builtin/branch.c msgid "branch copy failed" msgstr "ha fallat la còpia de la branca" +#: builtin/branch.c #, c-format msgid "created a copy of a misnamed branch '%s'" msgstr "s'ha creat una còpia d'una branca mal anomenada «%s»" +#: builtin/branch.c #, c-format msgid "renamed a misnamed branch '%s' away" msgstr "s'ha canviat el nom d'una branca «%s» mal anomenada" +#: builtin/branch.c #, c-format msgid "branch renamed to %s, but HEAD is not updated" msgstr "s'ha canviat el nom de la branca a %s, però HEAD no s'ha actualitzat" +#: builtin/branch.c msgid "branch is renamed, but update of config-file failed" msgstr "" "s'ha canviat el nom de la branca, però ha fallat l'actualització del fitxer " "de configuració" +#: builtin/branch.c msgid "branch is copied, but update of config-file failed" msgstr "" "s'ha copiat la branca, però ha fallat l'actualització del fitxer de " "configuració" +#: builtin/branch.c #, c-format msgid "" "Please edit the description for the branch\n" " %s\n" -"Lines starting with '%c' will be stripped.\n" +"Lines starting with '%s' will be stripped.\n" msgstr "" "Editeu la descripció de la branca\n" " %s\n" -"S'eliminaran les lÃnies que comencin amb «%c».\n" +"S'eliminaran les lÃnies que comencin amb «%s».\n" +"\"\n" +#: builtin/branch.c msgid "Generic options" msgstr "Opcions genèriques" +#: builtin/branch.c msgid "show hash and subject, give twice for upstream branch" msgstr "mostra el hash i l'assumpte, useu-lo dues vegades per a la branca font" +#: builtin/branch.c msgid "suppress informational messages" msgstr "omet els missatges informatius" +#: builtin/branch.c builtin/checkout.c builtin/submodule--helper.c msgid "set branch tracking configuration" msgstr "estableix la configuració del seguiment de la branca" +#: builtin/branch.c msgid "do not use" msgstr "no usar" +#: builtin/branch.c msgid "upstream" msgstr "font" +#: builtin/branch.c msgid "change the upstream info" msgstr "canvia la informació de font" +#: builtin/branch.c msgid "unset the upstream info" msgstr "treu la informació de la font" +#: builtin/branch.c msgid "use colored output" msgstr "usa sortida amb colors" +#: builtin/branch.c msgid "act on remote-tracking branches" msgstr "actua en branques amb seguiment remot" +#: builtin/branch.c msgid "print only branches that contain the commit" msgstr "imprimeix només les branques que continguin la comissió" +#: builtin/branch.c msgid "print only branches that don't contain the commit" msgstr "imprimeix només les branques que no continguin la comissió" +#: builtin/branch.c msgid "Specific git-branch actions:" msgstr "Accions de git-branch especÃfiques:" +#: builtin/branch.c msgid "list both remote-tracking and local branches" msgstr "llista les branques amb seguiment remot i les locals" +#: builtin/branch.c msgid "delete fully merged branch" msgstr "suprimeix la branca si està completament fusionada" +#: builtin/branch.c msgid "delete branch (even if not merged)" msgstr "suprimeix la branca (encara que no estigui fusionada)" +#: builtin/branch.c msgid "move/rename a branch and its reflog" -msgstr "mou/canvia de nom una branca i el seu registre de referència" +msgstr "mou/canvia de nom una branca i el seu registre de referències" +#: builtin/branch.c msgid "move/rename a branch, even if target exists" msgstr "mou/canvia de nom una branca, encara que el destà existeixi" +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c msgid "do not output a newline after empty formatted refs" msgstr "no emetis cap lÃnia nova després de refs amb format buit" +#: builtin/branch.c msgid "copy a branch and its reflog" -msgstr "copia una branca i el seu registre de referència" +msgstr "copia una branca i el seu registre de referències" +#: builtin/branch.c msgid "copy a branch, even if target exists" msgstr "copia una branca, encara que el destà existeixi" +#: builtin/branch.c msgid "list branch names" msgstr "llista els noms de branca" +#: builtin/branch.c msgid "show current branch name" msgstr "mostra el nom de la branca actual" +#: builtin/branch.c builtin/submodule--helper.c msgid "create the branch's reflog" -msgstr "crea el registre de referència de la branca" +msgstr "crea el registre de referències de la branca" +#: builtin/branch.c msgid "edit the description for the branch" msgstr "edita la descripció de la branca" +#: builtin/branch.c msgid "force creation, move/rename, deletion" msgstr "força creació, moviment/canvi de nom, supressió" +#: builtin/branch.c msgid "print only branches that are merged" msgstr "imprimeix només les branques que s'han fusionat" +#: builtin/branch.c msgid "print only branches that are not merged" msgstr "imprimeix només les branques que no s'han fusionat" +#: builtin/branch.c msgid "list branches in columns" msgstr "llista les branques en columnes" +#: builtin/branch.c builtin/for-each-ref.c builtin/notes.c builtin/tag.c msgid "object" msgstr "objecte" +#: builtin/branch.c msgid "print only branches of the object" msgstr "imprimeix només les branques de l'objecte" +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c msgid "sorting and filtering are case insensitive" msgstr "ordenació i filtratge distingeixen entre majúscules i minúscules" +#: builtin/branch.c builtin/ls-files.c msgid "recurse through submodules" msgstr "inclou recursivament els submòduls" +#: builtin/branch.c builtin/for-each-ref.c builtin/ls-files.c builtin/ls-tree.c +#: builtin/tag.c builtin/verify-tag.c msgid "format to use for the output" msgstr "format a usar en la sortida" +#: builtin/branch.c msgid "failed to resolve HEAD as a valid ref" msgstr "no s'ha pogut resoldre HEAD com a referència và lida" +#: builtin/branch.c builtin/clone.c msgid "HEAD not found below refs/heads!" msgstr "HEAD no trobat sota refs/heads!" +#: builtin/branch.c msgid "" "branch with --recurse-submodules can only be used if submodule." "propagateBranches is enabled" @@ -3089,58 +3856,74 @@ msgstr "" "la branca amb --recurse-submodules només es pot utilitzar si submodule." "propagateBranches està habilitat" +#: builtin/branch.c msgid "--recurse-submodules can only be used to create branches" msgstr "--recurse-submodules només es pot utilitzar per a crear branques" +#: builtin/branch.c msgid "branch name required" msgstr "cal el nom de branca" +#: builtin/branch.c msgid "cannot give description to detached HEAD" msgstr "no s'ha pogut donar la descripció al HEAD separat" +#: builtin/branch.c msgid "cannot edit description of more than one branch" msgstr "no es pot editar la descripció de més d'una branca" +#: builtin/branch.c msgid "cannot copy the current branch while not on any" msgstr "no es pot copiar la branca actual mentre no pertanyi a cap" +#: builtin/branch.c msgid "cannot rename the current branch while not on any" msgstr "" "no s'ha pogut canviar el nom de la branca actual mentre no pertanyi a cap" +#: builtin/branch.c msgid "too many branches for a copy operation" msgstr "hi ha massa branques per a una operació de còpia" +#: builtin/branch.c msgid "too many arguments for a rename operation" msgstr "hi ha massa arguments per a una operació de canvi de nom" +#: builtin/branch.c msgid "too many arguments to set new upstream" msgstr "hi ha massa arguments per a establir una nova font" +#: builtin/branch.c #, c-format msgid "" "could not set upstream of HEAD to %s when it does not point to any branch" msgstr "" "no s'ha pogut configurar la font de HEAD a %s quan no apunta a cap branca" +#: builtin/branch.c #, c-format msgid "no such branch '%s'" msgstr "no existeix la branca «%s»" +#: builtin/branch.c #, c-format msgid "branch '%s' does not exist" msgstr "la branca «%s» no existeix" +#: builtin/branch.c msgid "too many arguments to unset upstream" msgstr "hi ha massa arguments per a desassignar la font" +#: builtin/branch.c msgid "could not unset upstream of HEAD when it does not point to any branch" msgstr "no s'ha pogut desassignar la font del HEAD quan no apunta a cap branca" +#: builtin/branch.c #, c-format msgid "branch '%s' has no upstream information" msgstr "la branca «%s» no té informació de la font" +#: builtin/branch.c msgid "" "the -a, and -r, options to 'git branch' do not take a branch name.\n" "Did you mean to use: -a|-r --list <pattern>?" @@ -3148,6 +3931,7 @@ msgstr "" "les opcions -a, i -r, a «git branch» no prenen un nom de branca.\n" "VolÃeu utilitzar: -a|-r --list <patró>?" +#: builtin/branch.c msgid "" "the '--set-upstream' option is no longer supported. Please use '--track' or " "'--set-upstream-to' instead" @@ -3155,30 +3939,39 @@ msgstr "" "l'opció «--set-upstream» ja no és admesa. Utilitzeu en comptes «--track» o " "«--set-upstream-to»" +#: builtin/bugreport.c msgid "git version:\n" msgstr "versió de git:\n" +#: builtin/bugreport.c #, c-format msgid "uname() failed with error '%s' (%d)\n" msgstr "uname() ha fallat amb l'error «%s» (%d)\n" +#: builtin/bugreport.c msgid "compiler info: " msgstr "informació del compilador: " +#: builtin/bugreport.c msgid "libc info: " msgstr "informació de la libc: " +#: builtin/bugreport.c msgid "not run from a git repository - no hooks to show\n" msgstr "" "no s'està executant en un repositori de git - no hi ha lligams a mostrar\n" +#: builtin/bugreport.c msgid "" -"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n" +"git bugreport [(-o | --output-directory) <path>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]" msgstr "" -"git bugreport [(-o | --output-directory) <camÃ>] [(-s | --suffix) <format>]\n" +"git bugreport [(-o | --output-directory) <path>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]" +#: builtin/bugreport.c msgid "" "Thank you for filling out a Git bug report!\n" "Please answer the following questions to help us understand your issue.\n" @@ -3212,46 +4005,59 @@ msgstr "" "Reviseu la resta de l'informe d'error de sota.\n" "Podeu eliminar qualsevol lÃnia que vulgueu.\n" +#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c +#: parse-options.h msgid "mode" msgstr "mode" +#: builtin/bugreport.c msgid "" "create an additional zip archive of detailed diagnostics (default 'stats')" msgstr "" "crea un arxiu zip addicional amb diagnòstics detallats (per defecte «stats»)" +#: builtin/bugreport.c msgid "specify a destination for the bugreport file(s)" msgstr "especifiqueu una destinació per al fitxer de l'informe d'error" +#: builtin/bugreport.c msgid "specify a strftime format suffix for the filename(s)" msgstr "especifiqueu un sufix en format strftime per al nom de fitxer" +#: builtin/bugreport.c #, c-format msgid "unknown argument `%s'" msgstr "argument desconegut «%s»" +#: builtin/bugreport.c builtin/diagnose.c #, c-format msgid "could not create leading directories for '%s'" msgstr "no s'han pogut crear els directoris principals de «%s»" +#: builtin/bugreport.c builtin/diagnose.c #, c-format msgid "unable to create diagnostics archive %s" msgstr "no s'ha pogut crear l'arxiu de diagnòstic %s" +#: builtin/bugreport.c msgid "System Info" msgstr "Informació del sistema" +#: builtin/bugreport.c msgid "Enabled Hooks" msgstr "Habilita els lligams" +#: builtin/bugreport.c #, c-format msgid "unable to write to %s" msgstr "no s'ha pogut escriure a %s" +#: builtin/bugreport.c #, c-format msgid "Created new report at '%s'.\n" msgstr "S'ha creat un nou informe a «%s».\n" +#: builtin/bundle.c msgid "" "git bundle create [-q | --quiet | --progress]\n" " [--version=<version>] <file> <git-rev-list-args>" @@ -3259,83 +4065,112 @@ msgstr "" "git bundle create [-q | --quiet | --progress]\n" " [--version=<versió>] <fitxer> <git-rev-list-args>" +#: builtin/bundle.c msgid "git bundle verify [-q | --quiet] <file>" msgstr "git bundle verify [-q | --quiet] <fitxer>" +#: builtin/bundle.c msgid "git bundle list-heads <file> [<refname>...]" -msgstr "git bundle list-heads <fitxer> [<refname>...]" +msgstr "git bundle list-heads <fitxer> [<nom-referència>...]" +#: builtin/bundle.c msgid "git bundle unbundle [--progress] <file> [<refname>...]" -msgstr "git bundle unbundle [--progress] <fitxer> [<refname>...]" +msgstr "git bundle unbundle [--progress] <fitxer> [<nom-referència>...]" +#: builtin/bundle.c msgid "need a <file> argument" msgstr "necessita un argument <fitxer>" +#: builtin/bundle.c builtin/pack-objects.c msgid "do not show progress meter" msgstr "no mostris l'indicador de progrés" +#: builtin/bundle.c builtin/pack-objects.c msgid "show progress meter" msgstr "mostra l'indicador de progrés" +#: builtin/bundle.c msgid "historical; same as --progress" msgstr "històric; el mateix que --progress" +#: builtin/bundle.c msgid "historical; does nothing" msgstr "històric; no fa res" +#: builtin/bundle.c msgid "specify bundle format version" msgstr "especifica la versió del format del farcell" +#: builtin/bundle.c msgid "Need a repository to create a bundle." msgstr "Cal un repositori per a crear un farcell." +#: builtin/bundle.c msgid "do not show bundle details" msgstr "no mostris els detalls del farcell" +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "cal un repositori per a verificar un farcell" + +#: builtin/bundle.c #, c-format msgid "%s is okay\n" msgstr "%s està bé\n" +#: builtin/bundle.c msgid "Need a repository to unbundle." msgstr "Cal un repositori per a desfer un farcell." +#: builtin/bundle.c msgid "Unbundling objects" msgstr "S'estan desagrupant objectes" +#: builtin/cat-file.c merge-recursive.c #, c-format msgid "cannot read object %s '%s'" msgstr "no es pot llegir l'objecte %s «%s»" +#: builtin/cat-file.c msgid "flush is only for --buffer mode" msgstr "flush només és per al mode --buffer" +#: builtin/cat-file.c msgid "empty command in input" msgstr "ordre buida en l'entrada" +#: builtin/cat-file.c #, c-format msgid "whitespace before command: '%s'" msgstr "espai en blanc abans de l'ordre: «%s»" +#: builtin/cat-file.c #, c-format msgid "%s requires arguments" msgstr "%s requereix arguments" +#: builtin/cat-file.c #, c-format msgid "%s takes no arguments" -msgstr "%s no accepta cap valor" +msgstr "%s no accepta arguments" +#: builtin/cat-file.c msgid "only one batch option may be specified" msgstr "només es pot especificar una opció per lots" +#: builtin/cat-file.c msgid "git cat-file <type> <object>" msgstr "git cat-file <tipus> <objecte>" +#: builtin/cat-file.c msgid "git cat-file (-e | -p) <object>" msgstr "git cat-file (-e | -p) <objecte>" +#: builtin/cat-file.c msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" msgstr "git cat-file (-t | -s) [--allow-unknown-type] <objecte>" +#: builtin/cat-file.c msgid "" "git cat-file (--textconv | --filters)\n" " [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" @@ -3343,6 +4178,7 @@ msgstr "" "git cat-file (--textconv | --filters)\n" " [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" +#: builtin/cat-file.c msgid "" "git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" "objects]\n" @@ -3354,114 +4190,147 @@ msgstr "" " [--buffer] [--follow-symlinks] [--unordered]\n" " [--textconv | --filters] [-Z]" +#: builtin/cat-file.c msgid "Check object existence or emit object contents" msgstr "Comprova l'existència de l'objecte o emet el contingut de l'objecte" +#: builtin/cat-file.c msgid "check if <object> exists" msgstr "comprova si <objecte> existeix" +#: builtin/cat-file.c msgid "pretty-print <object> content" msgstr "impressió embellida del contingut de l'<objecte>" +#: builtin/cat-file.c msgid "Emit [broken] object attributes" msgstr "Emet els atributs [broken] de l'objecte" +#: builtin/cat-file.c msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" msgstr "" "mostra el tipus d'objecte (un dels següents: «blob», «tree», «commit», " "«tag», ...)" +#: builtin/cat-file.c msgid "show object size" msgstr "mostra la mida de l'objecte" +#: builtin/cat-file.c msgid "allow -s and -t to work with broken/corrupt objects" msgstr "permet que -s i -t funcionin amb objectes trencats/malmesos" +#: builtin/cat-file.c builtin/log.c msgid "use mail map file" msgstr "usa el fitxer de mapa de correu" +#: builtin/cat-file.c msgid "Batch objects requested on stdin (or --batch-all-objects)" msgstr "Objectes de lots sol·licitats a stdin (o --batch-all-objects)" +#: builtin/cat-file.c msgid "show full <object> or <rev> contents" msgstr "mostra el contingut complet de <objecte> o <rev>" +#: builtin/cat-file.c msgid "like --batch, but don't emit <contents>" msgstr "com a --batch, però no emetis <contents>" +#: builtin/cat-file.c msgid "stdin is NUL-terminated" msgstr "l'entrada és acabada amb NUL" +#: builtin/cat-file.c msgid "stdin and stdout is NUL-terminated" msgstr "stdin i stdout estan terminats amb NUL" +#: builtin/cat-file.c msgid "read commands from stdin" msgstr "llegeix les ordres de stdin" +#: builtin/cat-file.c msgid "with --batch[-check]: ignores stdin, batches all known objects" msgstr "" "amb --batch[-check]: ignora stdin, posa en lots tots els objectes coneguts" +#: builtin/cat-file.c msgid "Change or optimize batch output" msgstr "Canvia o optimitza la sortida per lots" +#: builtin/cat-file.c msgid "buffer --batch output" msgstr "posa la sortida de --batch en memòria intermèdia" +#: builtin/cat-file.c msgid "follow in-tree symlinks" msgstr "segueix els enllaços simbòlics en l'arbre" +#: builtin/cat-file.c msgid "do not order objects before emitting them" msgstr "no ordenis els objectes abans d'emetre'ls" +#: builtin/cat-file.c msgid "" "Emit object (blob or tree) with conversion or filter (stand-alone, or with " "batch)" msgstr "" "Emet l'objecte (blob o arbre) amb conversió o filtre (stand-alone, o amb lot)" +#: builtin/cat-file.c msgid "run textconv on object's content" msgstr "executar textconv al contingut de l'objecte" +#: builtin/cat-file.c msgid "run filters on object's content" msgstr "executa els filtres al contingut de l'objecte" +#: builtin/cat-file.c msgid "blob|tree" msgstr "blob|tree" +#: builtin/cat-file.c msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "useu un <camÃ> per a (--textconv | --filters); no amb «batch»" +#: builtin/cat-file.c #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "«%s=<%s>» necessita «%s» o «%s»" +#: builtin/cat-file.c msgid "path|tree-ish" msgstr "path|tree-ish" +#: builtin/cat-file.c #, c-format msgid "'%s' requires a batch mode" msgstr "«%s» requereix un mode batch" +#: builtin/cat-file.c #, c-format msgid "'-%c' is incompatible with batch mode" msgstr "«-%c» és incompatible amb el model batch" +#: builtin/cat-file.c msgid "batch modes take no arguments" msgstr "el mode batch no accepta cap argument" +#: builtin/cat-file.c #, c-format msgid "<rev> required with '%s'" msgstr "<rev> requerida amb «%s»" +#: builtin/cat-file.c #, c-format msgid "<object> required with '-%c'" msgstr "<objecte> requerit amb «-%c»" +#: builtin/cat-file.c #, c-format msgid "only two arguments allowed in <type> <object> mode, not %d" msgstr "només es permeten dos arguments en el mode <tipus> <objecte>, no %d" +#: builtin/check-attr.c msgid "" "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " "<pathname>..." @@ -3469,198 +4338,269 @@ msgstr "" "git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " "<pathname>..." +#: builtin/check-attr.c msgid "" "git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" msgstr "" "git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" +#: builtin/check-attr.c msgid "report all attributes set on file" msgstr "informa de tots els atributs establerts en el fitxer" +#: builtin/check-attr.c msgid "use .gitattributes only from the index" msgstr "usa .gitattributes només des de l'Ãndex" +#: builtin/check-attr.c builtin/check-ignore.c builtin/hash-object.c msgid "read file names from stdin" msgstr "llegeix els noms de fitxer de stdin" +#: builtin/check-attr.c builtin/check-ignore.c msgid "terminate input and output records by a NUL character" msgstr "acaba els registres d'entrada i de sortida amb un carà cter NUL" +#: builtin/check-attr.c msgid "<tree-ish>" msgstr "<tree-ish>" +#: builtin/check-attr.c msgid "which tree-ish to check attributes at" msgstr "a quin tree-ish s'han de comprovar els atributs" +#: builtin/check-ignore.c builtin/checkout.c builtin/gc.c builtin/worktree.c msgid "suppress progress reporting" msgstr "omet els informes de progrés" +#: builtin/check-ignore.c msgid "show non-matching input paths" msgstr "mostra els camins d'entrada que no coincideixin" +#: builtin/check-ignore.c msgid "ignore index when checking" msgstr "ignora l'Ãndex en comprovar" +#: builtin/check-ignore.c msgid "cannot specify pathnames with --stdin" msgstr "no es poden especificar noms de camà amb --stdin" +#: builtin/check-ignore.c msgid "-z only makes sense with --stdin" msgstr "-z només té sentit amb --stdin" +#: builtin/check-ignore.c msgid "no path specified" msgstr "cap camà especificat" +#: builtin/check-ignore.c msgid "--quiet is only valid with a single pathname" msgstr "--quiet només és và lid amb un sol nom de camÃ" +#: builtin/check-ignore.c msgid "cannot have both --quiet and --verbose" msgstr "no es poden especificar --quiet i --verbose alhora" +#: builtin/check-ignore.c msgid "--non-matching is only valid with --verbose" msgstr "--non-matching és và lid només amb --verbose" +#: builtin/check-mailmap.c msgid "git check-mailmap [<options>] <contact>..." msgstr "git check-mailmap [<opcions>] <contacte>..." +#: builtin/check-mailmap.c msgid "also read contacts from stdin" msgstr "també llegeix els contactes des de stdin" -#, c-format -msgid "unable to parse contact: %s" -msgstr "no s'ha pogut analitzar el contacte: %s" +# no traduïsc mailmap +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from file" +msgstr "llegeix les entrades mailmap addicionals del fitxer" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "blob" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "llegeix entrades mailmap addicionals del blob" +#: builtin/check-mailmap.c msgid "no contacts specified" msgstr "no hi ha contactes especificats" +#: builtin/checkout--worker.c msgid "git checkout--worker [<options>]" msgstr "git checkout--worker [<opcions>]" +#: builtin/checkout--worker.c builtin/checkout-index.c builtin/column.c +#: builtin/submodule--helper.c builtin/worktree.c msgid "string" msgstr "cadena" +#: builtin/checkout--worker.c builtin/checkout-index.c msgid "when creating files, prepend <string>" msgstr "en crear fitxers, anteposa <cadena>" +#: builtin/checkout-index.c msgid "git checkout-index [<options>] [--] [<file>...]" msgstr "git checkout-index [<opcions>] [--] [<fitxer>...]" +#: builtin/checkout-index.c msgid "stage should be between 1 and 3 or all" msgstr "«stage» ha de ser entre 1 i 3 o all" +#: builtin/checkout-index.c msgid "check out all files in the index" msgstr "agafa tots els fitxers en l'Ãndex" +#: builtin/checkout-index.c msgid "do not skip files with skip-worktree set" msgstr "no ometis els fitxers amb skip-worktree establert" +#: builtin/checkout-index.c msgid "force overwrite of existing files" msgstr "força la sobreescriptura de fitxers existents" +#: builtin/checkout-index.c msgid "no warning for existing files and files not in index" msgstr "" "cap advertència per a fitxers existents i fitxers que no siguin a l'Ãndex" +#: builtin/checkout-index.c msgid "don't checkout new files" msgstr "no agafis fitxers nous" +#: builtin/checkout-index.c msgid "update stat information in the index file" msgstr "actualitza la informació d'estadÃstiques en el fitxer d'Ãndex" +#: builtin/checkout-index.c msgid "read list of paths from the standard input" msgstr "llegeix la llista de camins des de l'entrada està ndard" +#: builtin/checkout-index.c msgid "write the content to temporary files" msgstr "escriu el contingut a fitxers temporals" +#: builtin/checkout-index.c msgid "copy out the files from named stage" msgstr "copia els fitxers des de «stage» amb nom" +#: builtin/checkout.c msgid "git checkout [<options>] <branch>" msgstr "git checkout [<opcions>] <branca>" +#: builtin/checkout.c msgid "git checkout [<options>] [<branch>] -- <file>..." msgstr "git checkout [<opcions>] [<branca>] -- <fitxer>..." +#: builtin/checkout.c msgid "git switch [<options>] [<branch>]" msgstr "git switch [<opcions>] [<branca>]" +#: builtin/checkout.c msgid "git restore [<options>] [--source=<branch>] <file>..." msgstr "git restore [<opcions>] [--source=<branca>] <fitxer>..." +#: builtin/checkout.c #, c-format msgid "path '%s' does not have our version" msgstr "el camà «%s» no té la nostra versió" +#: builtin/checkout.c #, c-format msgid "path '%s' does not have their version" msgstr "el camà «%s» no té la seva versió" +#: builtin/checkout.c #, c-format msgid "path '%s' does not have all necessary versions" msgstr "el camà «%s» no té totes les versions necessà ries" +#: builtin/checkout.c #, c-format msgid "path '%s' does not have necessary versions" msgstr "el camà «%s» no té les versions necessà ries" +#: builtin/checkout.c #, c-format msgid "path '%s': cannot merge" msgstr "camà «%s»: no es pot fusionar" +#: builtin/checkout.c #, c-format msgid "Unable to add merge result for '%s'" msgstr "No s'ha pogut afegir el resultat de fusió per a «%s»" +#: builtin/checkout.c #, c-format msgid "Recreated %d merge conflict" msgid_plural "Recreated %d merge conflicts" msgstr[0] "Recreat un conflicte de fusió" msgstr[1] "Recreats %d conflictes de fusió" +#: builtin/checkout.c #, c-format msgid "Updated %d path from %s" msgid_plural "Updated %d paths from %s" -msgstr[0] "S'ha actualitzat %d camà des de %s" -msgstr[1] "S'han actualitzat %d camins des de %s" +msgstr[0] "S'ha actualitzat %d camà a partir de %s" +msgstr[1] "S'han actualitzat %d camins a partir de %s" +#: builtin/checkout.c #, c-format msgid "Updated %d path from the index" msgid_plural "Updated %d paths from the index" -msgstr[0] "S'ha actualitzat un camà des de l'Ãndex" -msgstr[1] "S'ha actualitzat %d camins des de l'Ãndex" +msgstr[0] "S'ha actualitzat %d camà a partir de l'Ãndex" +msgstr[1] "S'han actualitzat %d camins a partir de l'Ãndex" +#: builtin/checkout.c #, c-format msgid "'%s' cannot be used with updating paths" msgstr "«%s» no es pot usar amb actualització de camins" +#: builtin/checkout.c #, c-format msgid "Cannot update paths and switch to branch '%s' at the same time." msgstr "" "No es poden actualitzar els camins i canviar a la branca «%s» a la vegada." +#: builtin/checkout.c #, c-format msgid "neither '%s' or '%s' is specified" msgstr "no s'ha especificat ni «%s» ni «%s»" +#: builtin/checkout.c #, c-format msgid "'%s' must be used when '%s' is not specified" msgstr "«%s» s'ha d'utilitzar quan no s'especifica «%s»" +#: builtin/checkout.c #, c-format msgid "'%s' or '%s' cannot be used with %s" msgstr "«%s» o «%s» no poden utilitzar-se amb %s" +#: builtin/checkout.c #, c-format msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree" msgstr "«%s», «%s» o «%s» no es poden utilitzar en agafar un arbre" +#: builtin/checkout.c #, c-format msgid "path '%s' is unmerged" msgstr "el camà «%s» està sense fusionar" +#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c +#: merge-ort.c reset.c sequencer.c tree-walk.c +#, c-format +msgid "unable to read tree (%s)" +msgstr "no s'ha pogut llegir l'arbre (%s)" + +#: builtin/checkout.c msgid "you need to resolve your current index first" msgstr "heu de primer resoldre el vostre Ãndex actual" +#: builtin/checkout.c #, c-format msgid "" "cannot continue with staged changes in the following files:\n" @@ -3669,40 +4609,50 @@ msgstr "" "no es pot continuar amb els canvis «staged» als fitxers següents:\n" "%s" +#: builtin/checkout.c #, c-format msgid "Can not do reflog for '%s': %s\n" -msgstr "No es pot fer reflog per a «%s»: %s\n" +msgstr "No es pot fer «reflog» per a «%s»: %s\n" +#: builtin/checkout.c msgid "HEAD is now at" msgstr "HEAD ara és a" +#: builtin/checkout.c builtin/clone.c msgid "unable to update HEAD" msgstr "no s'ha pogut actualitzar HEAD" +#: builtin/checkout.c #, c-format msgid "Reset branch '%s'\n" msgstr "Restableix la branca «%s»\n" +#: builtin/checkout.c #, c-format msgid "Already on '%s'\n" msgstr "Ja esteu en «%s»\n" +#: builtin/checkout.c #, c-format msgid "Switched to and reset branch '%s'\n" msgstr "S'ha canviat i restablert a la branca «%s»\n" +#: builtin/checkout.c #, c-format msgid "Switched to a new branch '%s'\n" msgstr "S'ha canviat a la branca nova «%s»\n" +#: builtin/checkout.c #, c-format msgid "Switched to branch '%s'\n" msgstr "S'ha canviat a la branca «%s»\n" +#: builtin/checkout.c #, c-format msgid " ... and %d more.\n" msgstr " ... i %d més.\n" +#: builtin/checkout.c #, c-format msgid "" "Warning: you are leaving %d commit behind, not connected to\n" @@ -3725,6 +4675,7 @@ msgstr[1] "" "\n" "%s\n" +#: builtin/checkout.c #, c-format msgid "" "If you want to keep it by creating a new branch, this may be a good time\n" @@ -3751,15 +4702,19 @@ msgstr[1] "" " git branch <nom-de-branca-nova> %s\n" "\n" +#: builtin/checkout.c msgid "internal error in revision walk" msgstr "error intern en el passeig per revisions" +#: builtin/checkout.c msgid "Previous HEAD position was" msgstr "La posició de HEAD anterior era" +#: builtin/checkout.c msgid "You are on a branch yet to be born" msgstr "Sou en una branca que encara ha de néixer" +#: builtin/checkout.c #, c-format msgid "" "'%s' could be both a local file and a tracking branch.\n" @@ -3768,6 +4723,7 @@ msgstr "" "«%s» podria ser tant un fitxer local com una branca de seguiment.\n" "Useu -- (i opcionalment --no-guess) per a desambiguar-ho" +#: builtin/checkout.c msgid "" "If you meant to check out a remote tracking branch on, e.g. 'origin',\n" "you can do so by fully qualifying the name with the --track option:\n" @@ -3787,47 +4743,58 @@ msgstr "" "remota, p. ex. «origin» al remot, considereu configurar l'opció\n" "checkout.defaultRemote=origin en la vostra configuració." +#: builtin/checkout.c #, c-format msgid "'%s' matched multiple (%d) remote tracking branches" msgstr "«%s» coincideixen múltiples (%d) branques de seguiment remotes" +#: builtin/checkout.c msgid "only one reference expected" msgstr "només s'esperava una referència" +#: builtin/checkout.c #, c-format msgid "only one reference expected, %d given." msgstr "s'esperava només una referència, s'han donat %d." +#: builtin/checkout.c builtin/worktree.c #, c-format msgid "invalid reference: %s" msgstr "referència no và lida: %s" +#: builtin/checkout.c #, c-format msgid "reference is not a tree: %s" msgstr "la referència no és un arbre: %s" +#: builtin/checkout.c #, c-format msgid "a branch is expected, got tag '%s'" msgstr "s'espera una branca, s'ha obtingut l'etiqueta «%s»" +#: builtin/checkout.c #, c-format msgid "a branch is expected, got remote branch '%s'" msgstr "s'espera una branca, s'ha obtingut la branca remota «%s»" +#: builtin/checkout.c #, c-format msgid "a branch is expected, got '%s'" msgstr "s'espera una branca, s'ha obtingut «%s»" +#: builtin/checkout.c #, c-format msgid "a branch is expected, got commit '%s'" msgstr "s'espera una branca, s'ha obtingut la comissió «%s»" +#: builtin/checkout.c msgid "" "If you want to detach HEAD at the commit, try again with the --detach option." msgstr "" "Si voleu desacoblar HEAD a la comissió, torneu-ho a provar amb l'opció --" "detach." +#: builtin/checkout.c msgid "" "cannot switch branch while merging\n" "Consider \"git merge --quit\" or \"git worktree add\"." @@ -3835,6 +4802,7 @@ msgstr "" "no es pot canviar de branca mentre es fusiona\n" "Considereu usar «git merge --quit» o «git worktree add»." +#: builtin/checkout.c msgid "" "cannot switch branch in the middle of an am session\n" "Consider \"git am --quit\" or \"git worktree add\"." @@ -3842,6 +4810,7 @@ msgstr "" "no es pot canviar de branca en mig d'una sessió «am»\n" "Considereu usar «git am --quit» o «git worktree add»." +#: builtin/checkout.c msgid "" "cannot switch branch while rebasing\n" "Consider \"git rebase --quit\" or \"git worktree add\"." @@ -3849,6 +4818,7 @@ msgstr "" "no es pot canviar de branca mentre es fa «rebase»\n" "Considereu usar «git rebase --quit» o «git worktree add»." +#: builtin/checkout.c msgid "" "cannot switch branch while cherry-picking\n" "Consider \"git cherry-pick --quit\" or \"git worktree add\"." @@ -3856,6 +4826,7 @@ msgstr "" "no es pot canviar de branca mentre es fa «cherry-pick»\n" "Considereu usar «git cherry-pick --quit» o «git worktree add»." +#: builtin/checkout.c msgid "" "cannot switch branch while reverting\n" "Consider \"git revert --quit\" or \"git worktree add\"." @@ -3863,95 +4834,133 @@ msgstr "" "no es pot canviar de branca mentre s'està revertint\n" "Considereu «git revert --quit» o «git worktree add»." +#: builtin/checkout.c msgid "you are switching branch while bisecting" msgstr "s'està canviant la branca mentre es fa una bisecció" +#: builtin/checkout.c msgid "paths cannot be used with switching branches" msgstr "els camins no es poden usar amb canvi de branca" +#: builtin/checkout.c #, c-format msgid "'%s' cannot be used with switching branches" msgstr "«%s» no es pot usar amb canvi de branca" +# és com si faltara un objecte directe per a agafar +#: builtin/checkout.c +#, c-format +msgid "'%s' needs the paths to check out" +msgstr "«%s» necessita els camins per a agafar" + +#: builtin/checkout.c #, c-format msgid "'%s' cannot be used with '%s'" msgstr "«%s» no es pot usar amb «%s»" +#: builtin/checkout.c #, c-format msgid "'%s' cannot take <start-point>" msgstr "«%s» no pot prendre <start-point>" +#: builtin/checkout.c #, c-format msgid "Cannot switch branch to a non-commit '%s'" msgstr "No es pot canviar la branca a la no comissió «%s»" +#: builtin/checkout.c msgid "missing branch or commit argument" msgstr "manca branca o argument de comissió" +#: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "estil de conflicte desconegut «%s»" + +#: builtin/checkout.c msgid "perform a 3-way merge with the new branch" msgstr "realitza una fusió de 3 vies amb la branca nova" +#: builtin/checkout.c builtin/log.c parse-options.h msgid "style" msgstr "estil" +#: builtin/checkout.c msgid "conflict style (merge, diff3, or zdiff3)" msgstr "estil de conflicte (merge, diff3, o zdiff3)" +#: builtin/checkout.c builtin/worktree.c msgid "detach HEAD at named commit" msgstr "separa HEAD a la comissió anomenada" +#: builtin/checkout.c msgid "force checkout (throw away local modifications)" msgstr "agafa a la força (descarta qualsevol modificació local)" +#: builtin/checkout.c msgid "new-branch" msgstr "branca-nova" +#: builtin/checkout.c msgid "new unborn branch" msgstr "branca no nascuda nova" +#: builtin/checkout.c builtin/merge.c msgid "update ignored files (default)" msgstr "actualitza els fitxers ignorats (per defecte)" +#: builtin/checkout.c msgid "do not check if another worktree is holding the given ref" msgstr "no comprovis si un altre arbre de treball té la referència donada" +#: builtin/checkout.c msgid "checkout our version for unmerged files" msgstr "agafa la versió nostra dels fitxers sense fusionar" +#: builtin/checkout.c msgid "checkout their version for unmerged files" msgstr "agafa la versió seva dels fitxers sense fusionar" +#: builtin/checkout.c msgid "do not limit pathspecs to sparse entries only" msgstr "no limitis les especificacions de camà només a entrades disperses" +#: builtin/checkout.c #, c-format msgid "options '-%c', '-%c', and '%s' cannot be used together" msgstr "les opcions «-%c», «-%c», i «%s» no es poden usar juntes" +#: builtin/checkout.c msgid "--track needs a branch name" msgstr "--track necessita un nom de branca" +#: builtin/checkout.c #, c-format msgid "missing branch name; try -%c" msgstr "falta el nom de la branca; proveu -%c" +#: builtin/checkout.c #, c-format msgid "could not resolve %s" msgstr "no es pot resoldre %s" +#: builtin/checkout.c msgid "invalid path specification" msgstr "especificació de camà no và lida" +#: builtin/checkout.c #, c-format msgid "'%s' is not a commit and a branch '%s' cannot be created from it" msgstr "" "«%s» no és una comissió i la branca «%s» no es pot crear a partir d'aquesta " "comissió" +#: builtin/checkout.c #, c-format msgid "git checkout: --detach does not take a path argument '%s'" msgstr "git checkout: --detach no accepta un argument de camà «%s»" +#: builtin/checkout.c msgid "" "git checkout: --ours/--theirs, --force and --merge are incompatible when\n" "checking out of the index." @@ -3959,54 +4968,72 @@ msgstr "" "git checkout: --ours/--theirs, --force i --merge són incompatibles en\n" "agafar de l'Ãndex." +#: builtin/checkout.c msgid "you must specify path(s) to restore" msgstr "heu d'especificar el camà o camins a restaurar" +#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c +#: builtin/submodule--helper.c builtin/worktree.c msgid "branch" msgstr "branca" +#: builtin/checkout.c msgid "create and checkout a new branch" msgstr "crea i agafa una branca nova" +#: builtin/checkout.c msgid "create/reset and checkout a branch" msgstr "crea/restableix i agafa una branca" +#: builtin/checkout.c msgid "create reflog for new branch" -msgstr "crea un registre de referència per a la branca nova" +msgstr "crea un registre de referències per a la branca nova" +#: builtin/checkout.c msgid "second guess 'git checkout <no-such-branch>' (default)" msgstr "segona deducció «git checkout <no-such-branch>» (per defecte)" +#: builtin/checkout.c msgid "use overlay mode (default)" msgstr "utilitza el mode de superposició (per defecte)" +#: builtin/checkout.c msgid "create and switch to a new branch" msgstr "crea i canvia a una branca nova" +#: builtin/checkout.c msgid "create/reset and switch to a branch" msgstr "crea/restableix i canvia a una branca" +#: builtin/checkout.c msgid "second guess 'git switch <no-such-branch>'" msgstr "segona deducció «git switch <no-such-branch>»" +#: builtin/checkout.c msgid "throw away local modifications" msgstr "descarta les modificacions locals" +#: builtin/checkout.c msgid "which tree-ish to checkout from" msgstr "des de quin arbre agafar" +#: builtin/checkout.c msgid "restore the index" msgstr "restaura l'Ãndex" +#: builtin/checkout.c msgid "restore the working tree (default)" msgstr "restaura l'arbre de treball (per defecte)" +#: builtin/checkout.c msgid "ignore unmerged entries" msgstr "ignora les entrades sense fusionar" +#: builtin/checkout.c msgid "use overlay mode" msgstr "utilitza el mode de superposició" +#: builtin/clean.c msgid "" "git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] " "[<pathspec>...]" @@ -4014,36 +5041,45 @@ msgstr "" "git clean [-d] [-f] [-i] [-n] [-q] [-e <patró>] [-x | -X] [--] " "[<pathspec>...]" +#: builtin/clean.c #, c-format msgid "Removing %s\n" msgstr "S'està eliminant %s\n" +#: builtin/clean.c #, c-format msgid "Would remove %s\n" msgstr "Eliminaria %s\n" +#: builtin/clean.c #, c-format msgid "Skipping repository %s\n" msgstr "S'està ometent el repositori %s\n" +#: builtin/clean.c #, c-format msgid "Would skip repository %s\n" msgstr "Ometria el repositori %s\n" +#: builtin/clean.c midx.c #, c-format msgid "failed to remove %s" msgstr "s'ha produït un error en eliminar %s" +#: builtin/clean.c #, c-format msgid "could not lstat %s\n" msgstr "no s'ha pogut fer lstat %s\n" +#: builtin/clean.c msgid "Refusing to remove current working directory\n" msgstr "S'ha rebutjat suprimir el directori de treball actual\n" +#: builtin/clean.c msgid "Would refuse to remove current working directory\n" msgstr "Es rebutjarà eliminar el directori de treball actual\n" +#: builtin/clean.c #, c-format msgid "" "Prompt help:\n" @@ -4056,6 +5092,7 @@ msgstr "" "foo - selecciona un Ãtem basat en un prefix únic\n" " - (buit) no seleccionis res\n" +#: builtin/clean.c #, c-format msgid "" "Prompt help:\n" @@ -4076,26 +5113,32 @@ msgstr "" "* - tria tots els Ãtems\n" " - (buit) finalitza la selecció\n" +#: builtin/clean.c #, c-format msgid "Huh (%s)?\n" msgstr "Perdó (%s)?\n" +#: builtin/clean.c #, c-format msgid "Input ignore patterns>> " msgstr "Introduïu els patrons a ignorar>> " +#: builtin/clean.c #, c-format msgid "WARNING: Cannot find items matched by: %s" msgstr "ADVERTÈNCIA: No es poden trobar Ãtems que coincideixin amb: %s" +#: builtin/clean.c msgid "Select items to delete" msgstr "Selecciona els Ãtems a suprimir" #. TRANSLATORS: Make sure to keep [y/N] as is +#: builtin/clean.c #, c-format msgid "Remove %s [y/N]? " msgstr "Voleu eliminar %s [y/N]? " +#: builtin/clean.c msgid "" "clean - start cleaning\n" "filter by pattern - exclude items from deletion\n" @@ -4113,216 +5156,286 @@ msgstr "" "help - aquesta pantalla\n" "? - ajuda de selecció manual" +#: builtin/clean.c msgid "Would remove the following item:" msgid_plural "Would remove the following items:" msgstr[0] "Eliminaria l'Ãtem següent:" msgstr[1] "Eliminaria els Ãtems següents:" +#: builtin/clean.c msgid "No more files to clean, exiting." msgstr "No hi ha més fitxers a netejar; s'està sortint." +#: builtin/clean.c msgid "do not print names of files removed" msgstr "no imprimeixis els noms dels fitxers eliminats" +#: builtin/clean.c msgid "force" msgstr "força" +#: builtin/clean.c msgid "interactive cleaning" msgstr "neteja interactiva" +#: builtin/clean.c msgid "remove whole directories" msgstr "elimina directoris sencers" +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h msgid "pattern" msgstr "patró" +#: builtin/clean.c msgid "add <pattern> to ignore rules" msgstr "afegiu <patró> per a ignorar les regles" +#: builtin/clean.c msgid "remove ignored files, too" msgstr "elimina els fitxers ignorats, també" +#: builtin/clean.c msgid "remove only ignored files" msgstr "elimina només els fitxers ignorats" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce està establerta en cert i ni -i, -n ni -f s'han indicat; " -"refusant netejar" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" +#: builtin/clean.c +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce és per defecte cert i ni -i, -n ni -f s'han indicat; " -"refusant netejar" +"clean.requireForce està establert a cert i no s'ha indicat -f : es rebutja " +"netejar" +#: builtin/clone.c msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<opcions>] [--] <repositori> [<directori>]" +#: builtin/clone.c msgid "don't clone shallow repository" msgstr "no clonis un repositori superficial" +#: builtin/clone.c msgid "don't create a checkout" msgstr "no facis cap agafament" +#: builtin/clone.c builtin/init-db.c msgid "create a bare repository" msgstr "crea un repositori nu" -msgid "create a mirror repository (implies bare)" -msgstr "crea un repositori mirall (implica bare)" +#: builtin/clone.c +msgid "create a mirror repository (implies --bare)" +msgstr "crear un repositori mirall (implica --bare)" +#: builtin/clone.c msgid "to clone from a local repository" msgstr "per a clonar des d'un repositori local" +#: builtin/clone.c msgid "don't use local hardlinks, always copy" msgstr "no usis enllaços durs locals, sempre copia" +#: builtin/clone.c msgid "setup as shared repository" msgstr "configura com a repositori compartit" +#: builtin/clone.c msgid "pathspec" msgstr "especificació de camÃ" +#: builtin/clone.c msgid "initialize submodules in the clone" msgstr "inicialitza els submòduls en el clon" +#: builtin/clone.c msgid "number of submodules cloned in parallel" msgstr "nombre de submòduls clonats en paral·lel" +#: builtin/clone.c builtin/init-db.c msgid "template-directory" msgstr "directori-de-plantilla" +#: builtin/clone.c builtin/init-db.c msgid "directory from which templates will be used" msgstr "directori des del qual s'usaran les plantilles" +#: builtin/clone.c builtin/submodule--helper.c msgid "reference repository" msgstr "repositori de referència" +#: builtin/clone.c builtin/submodule--helper.c msgid "use --reference only while cloning" msgstr "usa --reference només en clonar" +#: builtin/clone.c builtin/column.c builtin/fmt-merge-msg.c builtin/init-db.c +#: builtin/merge-file.c builtin/merge.c builtin/pack-objects.c builtin/repack.c +#: builtin/submodule--helper.c t/helper/test-simple-ipc.c msgid "name" msgstr "nom" +#: builtin/clone.c msgid "use <name> instead of 'origin' to track upstream" msgstr "usa <nom> en lloc d'«origin» per a seguir la font" +#: builtin/clone.c msgid "checkout <branch> instead of the remote's HEAD" msgstr "agafa <branca> en lloc de la HEAD del remot" +#: builtin/clone.c msgid "path to git-upload-pack on the remote" msgstr "camà a git-upload-pack en el remot" +#: builtin/clone.c builtin/fetch.c builtin/pull.c msgid "depth" msgstr "profunditat" +#: builtin/clone.c msgid "create a shallow clone of that depth" msgstr "crea un clon superficial d'aquesta profunditat" +#: builtin/clone.c msgid "create a shallow clone since a specific time" msgstr "crea un clon superficial des d'una data especÃfica" +#: builtin/clone.c builtin/fetch.c builtin/pull.c builtin/rebase.c +#: builtin/replay.c msgid "revision" msgstr "revisió" +#: builtin/clone.c builtin/fetch.c builtin/pull.c msgid "deepen history of shallow clone, excluding rev" msgstr "aprofundeix la història d'un clon superficial, excloent una revisió" +#: builtin/clone.c builtin/submodule--helper.c msgid "clone only one branch, HEAD or --branch" msgstr "clona només una branca, HEAD o --branch" +#: builtin/clone.c msgid "don't clone any tags, and make later fetches not to follow them" msgstr "" "no cloneu cap etiqueta, i feu que els «fetch» següents no les segueixin" +#: builtin/clone.c msgid "any cloned submodules will be shallow" msgstr "qualsevol submòdul clonat serà superficial" +#: builtin/clone.c builtin/init-db.c msgid "gitdir" msgstr "directori de git" +#: builtin/clone.c builtin/init-db.c msgid "separate git dir from working tree" msgstr "separa el directori de git de l'arbre de treball" +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c msgid "specify the reference format to use" msgstr "especifiqueu el format de referència a usar" +#: builtin/clone.c msgid "key=value" msgstr "clau=valor" +#: builtin/clone.c msgid "set config inside the new repository" msgstr "estableix la configuració dins del repositori nou" +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c msgid "server-specific" msgstr "especÃfic al servidor" +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c msgid "option to transmit" msgstr "opció a transmetre" +#: builtin/clone.c msgid "apply partial clone filters to submodules" msgstr "aplica els filtres de clonatge parcial als submòduls" +#: builtin/clone.c msgid "any cloned submodules will use their remote-tracking branch" msgstr "qualsevol submòdul clonat utilitzarà la seva branca de seguiment remot" +#: builtin/clone.c msgid "initialize sparse-checkout file to include only files at root" msgstr "" "inicialitza el fitxer «sparse-checkout» per a incloure només els fitxers a " "l'arrel" +#: builtin/clone.c msgid "uri" msgstr "uri" +#: builtin/clone.c msgid "a URI for downloading bundles before fetching from origin remote" msgstr "un URI per a baixar paquets abans d'obtenir des del remot origen" +#: builtin/clone.c #, c-format msgid "info: Could not add alternate for '%s': %s\n" msgstr "info: No s'ha pogut afegir un alternatiu per a «%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'ha produït un error en fer stat a «%s»" +#: builtin/clone.c #, c-format msgid "%s exists and is not a directory" msgstr "%s existeix i no és directori" +#: builtin/clone.c #, c-format msgid "'%s' is a symlink, refusing to clone with --local" msgstr "«%s» és un enllaç simbòlic, es rebutja clonar amb --local" +#: builtin/clone.c #, c-format msgid "failed to start iterator over '%s'" msgstr "no s'ha pogut iniciar l'iterador sobre «%s»" +#: builtin/clone.c #, c-format msgid "symlink '%s' exists, refusing to clone with --local" msgstr "l'enllaç simbòlic «%s» existeix, es rebutja a clonar amb --local" +#: builtin/clone.c compat/precompose_utf8.c #, c-format msgid "failed to unlink '%s'" msgstr "s'ha produït un error en desenllaçar «%s»" +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "no es pot comprovar l'enllaç fÃsic en «%s»" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "l'enllaç fÃsic és diferent de la font en «%s»" + +#: builtin/clone.c #, c-format msgid "failed to create link '%s'" msgstr "s'ha produït un error en crear l'enllaç «%s»" +#: builtin/clone.c #, c-format msgid "failed to copy file to '%s'" msgstr "s'ha produït un error en copiar el fitxer a «%s»" +#: builtin/clone.c refs/files-backend.c #, c-format msgid "failed to iterate over '%s'" msgstr "no s'ha pogut iterar sobre «%s»" +#: builtin/clone.c #, c-format msgid "done.\n" msgstr "fet.\n" +#: builtin/clone.c msgid "" "Clone succeeded, but checkout failed.\n" "You can inspect what was checked out with 'git status'\n" @@ -4332,83 +5445,106 @@ msgstr "" "Podeu inspeccionar el que s'ha agafat amb «git status»\n" "i tornar-ho a provar amb «git restore --source=HEAD :/»\n" +#: builtin/clone.c #, c-format msgid "Could not find remote branch %s to clone." msgstr "No s'ha pogut trobar la branca remota %s per a clonar." +#: builtin/clone.c fetch-pack.c msgid "remote did not send all necessary objects" msgstr "el remot no ha enviat tots els objectes necessaris" +#: builtin/clone.c #, c-format msgid "unable to update %s" msgstr "no s'ha pogut actualitzar %s" +#: builtin/clone.c msgid "failed to initialize sparse-checkout" msgstr "no s'ha pogut inicialitzar «sparse-checkout»" +#: builtin/clone.c msgid "remote HEAD refers to nonexistent ref, unable to checkout" msgstr "" -"la HEAD remot es refereix a una referència que no existeix, no s'ha pogut " +"el HEAD remot es refereix a una referència que no existeix, no s'ha pogut " "agafar" +#: builtin/clone.c msgid "unable to checkout working tree" msgstr "no s'ha pogut agafar l'arbre de treball" +#: builtin/clone.c msgid "unable to write parameters to config file" msgstr "no s'han pogut escriure els parà metres al fitxer de configuració" +#: builtin/clone.c msgid "cannot repack to clean up" msgstr "no es pot reempaquetar per a netejar" +#: builtin/clone.c msgid "cannot unlink temporary alternates file" msgstr "no es pot desenllaçar el fitxer d'alternatives temporal" +#: builtin/clone.c msgid "Too many arguments." msgstr "Hi ha massa arguments." +#: builtin/clone.c scalar.c msgid "You must specify a repository to clone." msgstr "Heu d'especificar un repositori per a clonar." +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c #, c-format msgid "unknown ref storage format '%s'" msgstr "el format d'emmagatzematge de referència «%s» és desconegut" +#: builtin/clone.c #, c-format msgid "repository '%s' does not exist" msgstr "el repositori «%s» no existeix" +#: builtin/clone.c builtin/fetch.c #, c-format msgid "depth %s is not a positive number" msgstr "la profunditat %s no és un nombre positiu" +#: builtin/clone.c #, c-format msgid "destination path '%s' already exists and is not an empty directory." msgstr "el camà destà «%s» ja existeix i no és un directori buit." +#: builtin/clone.c #, c-format msgid "repository path '%s' already exists and is not an empty directory." msgstr "el camà destà «%s» ja existeix i no és un directori buit." +#: builtin/clone.c #, c-format msgid "working tree '%s' already exists." msgstr "l'arbre de treball «%s» ja existeix." +#: builtin/clone.c builtin/difftool.c builtin/log.c builtin/worktree.c #, c-format msgid "could not create leading directories of '%s'" msgstr "no s'han pogut crear els directoris inicials de «%s»" +#: builtin/clone.c #, c-format msgid "could not create work tree dir '%s'" msgstr "no s'ha pogut crear el directori d'arbre de treball «%s»" +#: builtin/clone.c #, c-format msgid "Cloning into bare repository '%s'...\n" msgstr "S'està clonant al repositori nu «%s»...\n" +#: builtin/clone.c #, c-format msgid "Cloning into '%s'...\n" msgstr "S'està clonant a «%s»...\n" +#: builtin/clone.c msgid "" "clone --recursive is not compatible with both --reference and --reference-if-" "able" @@ -4416,85 +5552,115 @@ msgstr "" "clone --recursive no és compatible amb ambdós --reference i --reference-if-" "able" +#: builtin/clone.c builtin/remote.c #, c-format msgid "'%s' is not a valid remote name" msgstr "«%s» no és un nom de remot và lid" +#: builtin/clone.c msgid "--depth is ignored in local clones; use file:// instead." msgstr "--depth s'ignora en els clons locals; useu file:// en lloc d'això." +#: builtin/clone.c msgid "--shallow-since is ignored in local clones; use file:// instead." msgstr "" "--shallow-since s'ignora en els clons locals; useu file:// en lloc d'això." +#: builtin/clone.c msgid "--shallow-exclude is ignored in local clones; use file:// instead." msgstr "" "--shallow-exclude s'ignora en els clons locals; useu file:// en lloc d'això." +#: builtin/clone.c msgid "--filter is ignored in local clones; use file:// instead." msgstr "--filter s'ignora en els clons locals; useu file:// en lloc d'això." +#: builtin/clone.c fetch-pack.c msgid "source repository is shallow, reject to clone." msgstr "el repositori font és superficial, es rebutja clonar-ho." +#: builtin/clone.c msgid "source repository is shallow, ignoring --local" msgstr "el repositori font és superficial, s'està ignorant --local" +#: builtin/clone.c msgid "--local is ignored" msgstr "--local s'ignora" +#: builtin/clone.c msgid "cannot clone from filtered bundle" msgstr "no es pot clonar des del farell filtrat" +#: builtin/clone.c msgid "failed to initialize the repo, skipping bundle URI" msgstr "no s'ha pogut inicialitzar el repositori, s'omet l'URI del paquet" +#: builtin/clone.c #, c-format msgid "failed to fetch objects from bundle URI '%s'" msgstr "no s'han pogut obtenir els objectes de l'URI del paquet «%s»" +#: builtin/clone.c msgid "failed to fetch advertised bundles" msgstr "no s'han pogut obtenir els paquets anunciats" +#: builtin/clone.c msgid "remote transport reported error" msgstr "el transport remot ha informat d'un error" +#: builtin/clone.c #, c-format msgid "Remote branch %s not found in upstream %s" msgstr "La branca remota %s no es troba en la font %s" +#: builtin/clone.c msgid "You appear to have cloned an empty repository." msgstr "Sembla que heu clonat un repositori buit." +#: builtin/column.c msgid "git column [<options>]" msgstr "git column [<opcions>]" +#: builtin/column.c msgid "lookup config vars" msgstr "cerca les variables de configuració" +#: builtin/column.c msgid "layout to use" msgstr "disposició a usar" +#: builtin/column.c msgid "maximum width" msgstr "amplada mà xima" +#: builtin/column.c msgid "padding space on left border" msgstr "espai de farciment al marge esquerre" +#: builtin/column.c msgid "padding space on right border" msgstr "espai de farciment al marge dret" +#: builtin/column.c msgid "padding space between columns" msgstr "espai de farciment entre columnes" +#: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "%s ha de ser no negatiu" + +#: builtin/column.c msgid "--command must be the first argument" msgstr "--command ha de ser el primer argument" +#: builtin/commit-graph.c msgid "" "git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" msgstr "" "git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" +#: builtin/commit-graph.c msgid "" "git commit-graph write [--object-dir <dir>] [--append]\n" " [--split[=<strategy>]] [--reachable | --stdin-packs | " @@ -4510,131 +5676,169 @@ msgstr "" "[no-]progress]\n" " <split-options>" +#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c msgid "dir" msgstr "directori" +#: builtin/commit-graph.c msgid "the object directory to store the graph" msgstr "el directori d'objectes a emmagatzemar al graf" +#: builtin/commit-graph.c msgid "if the commit-graph is split, only verify the tip file" msgstr "" "si el graf de comissions està dividit només, verifica el fitxer de consell" +#: builtin/commit-graph.c #, c-format msgid "Could not open commit-graph '%s'" msgstr "No s'ha pogut obrir el graf de comissions «%s»" +#: builtin/commit-graph.c #, c-format msgid "could not open commit-graph chain '%s'" msgstr "no s'ha pogut obrir la cadena «%s» del graf de comissions" +#: builtin/commit-graph.c #, c-format msgid "unrecognized --split argument, %s" msgstr "argument --split no reconegut, %s" +#: builtin/commit-graph.c #, c-format msgid "unexpected non-hex object ID: %s" msgstr "ID de l'objecte no hexadecimal inesperat: %s" +#: builtin/commit-graph.c #, c-format msgid "invalid object: %s" msgstr "no és un objecte và lid: %s" +#: builtin/commit-graph.c parse-options-cb.c #, c-format msgid "option `%s' expects a numerical value" msgstr "l'opció «%s» espera un valor numèric" +#: builtin/commit-graph.c msgid "start walk at all refs" msgstr "comença el recorregut en totes les referències" +#: builtin/commit-graph.c msgid "scan pack-indexes listed by stdin for commits" msgstr "explora els Ãndexs del paquet llistats per a stdin per a comissions" +#: builtin/commit-graph.c msgid "start walk at commits listed by stdin" msgstr "comença el recorregut per les comissions llistades per stdin" +#: builtin/commit-graph.c msgid "include all commits already in the commit-graph file" msgstr "inclou ja totes les comissions al fitxer del graf de comissions" +#: builtin/commit-graph.c msgid "enable computation for changed paths" msgstr "habilita la computació per als camins canviats" +#: builtin/commit-graph.c msgid "allow writing an incremental commit-graph file" msgstr "permet escriure un fitxer de graf de comissions incrementals" +#: builtin/commit-graph.c msgid "maximum number of commits in a non-base split commit-graph" msgstr "" "nombre mà xim de comissions en un graf de comissions separades sense base" +#: builtin/commit-graph.c msgid "maximum ratio between two levels of a split commit-graph" msgstr "rà tio mà xima entre dos nivells d'un graf de comissions dividit" +#: builtin/commit-graph.c msgid "only expire files older than a given date-time" msgstr "fes caducar només els objectes més antics que l'hora i data donades" +#: builtin/commit-graph.c msgid "maximum number of changed-path Bloom filters to compute" -msgstr "nombre mà xim de canvis de camà en filtres Bloom a calcular" +msgstr "nombre mà xim de canvis de camà en filtres de Bloom a calcular" +#: builtin/commit-graph.c msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs" -msgstr "usa com a mà xim un --reachable, --stdin-commits, o --stdin-packs" +msgstr "usa com a mà xim un entre --reachable, --stdin-commits, o --stdin-packs" +#: builtin/commit-graph.c msgid "Collecting commits from input" msgstr "S'estan recollint les comissions de l'entrada" +#: builtin/commit-tree.c msgid "git commit-tree <tree> [(-p <parent>)...]" -msgstr "git commit-tree <tree> [(-p <pare>)...]" +msgstr "git commit-tree <arbre> [(-p <pare>)...]" +#: builtin/commit-tree.c msgid "" "git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n" " [(-F <file>)...] <tree>" msgstr "" "git commit-tree [(-p <pare>)...] [-S[<keyid>]] [(-m <missatge>)...]\n" -" [(-F <fitxer>)...] <tree>" +" [(-F <fitxer>)...] <arbre>" +#: builtin/commit-tree.c #, c-format msgid "duplicate parent %s ignored" msgstr "s'han ignorat el pare %s duplicat" +#: builtin/commit-tree.c builtin/log.c #, c-format msgid "not a valid object name %s" msgstr "no és un nom d'objecte và lid %s" +#: builtin/commit-tree.c #, c-format msgid "git commit-tree: failed to read '%s'" msgstr "git commit-tree: ha fallat en llegir «%s»" +#: builtin/commit-tree.c #, c-format msgid "git commit-tree: failed to close '%s'" msgstr "git commit-tree: ha fallat en tancar «%s»" +#: builtin/commit-tree.c msgid "parent" msgstr "pare" +#: builtin/commit-tree.c msgid "id of a parent commit object" msgstr "id d'un objecte de comissió pare" +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/notes.c +#: builtin/stash.c builtin/tag.c msgid "message" msgstr "missatge" +#: builtin/commit-tree.c builtin/commit.c msgid "commit message" msgstr "missatge de comissió" +#: builtin/commit-tree.c msgid "read commit log message from file" msgstr "llegeix el missatge de registre de comissió des d'un fitxer" +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/pull.c +#: builtin/revert.c msgid "GPG sign commit" msgstr "signa la comissió amb GPG" +#: builtin/commit-tree.c msgid "must give exactly one tree" msgstr "ha de donar exactament un arbre" +#: builtin/commit-tree.c msgid "git commit-tree: failed to read" msgstr "git commit-tree: ha fallat en llegir" +#: builtin/commit.c msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4644,17 +5848,19 @@ msgid "" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <comissió> | --fixup [(amend|" -"reword):]<comissió>)]\n" +"reword):]<comissió>]\n" " [-F <fitxer> | -m <msg>] [--reset-author] [--allow-empty]\n" -" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" -" [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=<autor>]\n" +" [--date=<data>] [--cleanup=<mode>] [--[no-]status]\n" " [-i | -o] [--pathspec-from-file=<fitxer> [--pathspec-file-nul]]\n" -" [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" -" [--] [<pathspec>...]" +" [(--trailer <token>[(=|:)<valor>])...] [-S[<id-clau>]]\n" +" [--] [<especificació-camÃ>...]" +#: builtin/commit.c msgid "git status [<options>] [--] [<pathspec>...]" msgstr "git status [<opcions>] [--] [<pathspec>...]" +#: builtin/commit.c msgid "" "You asked to amend the most recent commit, but doing so would make\n" "it empty. You can repeat your command with --allow-empty, or you can\n" @@ -4664,6 +5870,7 @@ msgstr "" "deixaria buida. Podeu repetir la vostra ordre amb --allow-empty, o\n" "podeu eliminar la comissió per complet amb «git reset HEAD^».\n" +#: builtin/commit.c msgid "" "The previous cherry-pick is now empty, possibly due to conflict resolution.\n" "If you wish to commit it anyway, use:\n" @@ -4678,12 +5885,15 @@ msgstr "" " git commit --allow-empty\n" "\n" +#: builtin/commit.c msgid "Otherwise, please use 'git rebase --skip'\n" msgstr "Altrament, si us plau useu «git rebase --skip»\n" +#: builtin/commit.c msgid "Otherwise, please use 'git cherry-pick --skip'\n" msgstr "Altrament, si us plau useu «git cherry-pick --skip»\n" +#: builtin/commit.c msgid "" "and then use:\n" "\n" @@ -4705,57 +5915,74 @@ msgstr "" " git cherry-pick --skip\n" "\n" +#: builtin/commit.c read-cache.c msgid "updating files failed" msgstr "s'ha produït un error en actualitzar els fitxers" +#: builtin/commit.c msgid "failed to unpack HEAD tree object" msgstr "s'ha produït un error en desempaquetar l'objecte d'arbre HEAD" +#: builtin/commit.c msgid "No paths with --include/--only does not make sense." msgstr "--include/--only no té sentit sense camÃ." +#: builtin/commit.c msgid "unable to create temporary index" msgstr "no s'ha pogut crear un Ãndex temporal" +#: builtin/commit.c msgid "interactive add failed" msgstr "l'afegiment interactiu ha fallat" +#: builtin/commit.c msgid "unable to update temporary index" msgstr "no s'ha pogut actualitzar l'Ãndex temporal" +#: builtin/commit.c msgid "Failed to update main cache tree" msgstr "S'ha produït un error en actualitzar l'arbre principal de memòria cau" +#: builtin/commit.c msgid "cannot do a partial commit during a merge." msgstr "no es pot fer una comissió parcial durant una fusió." +#: builtin/commit.c msgid "cannot do a partial commit during a cherry-pick." msgstr "no es pot fer una comissió parcial durant un «cherry pick»." +#: builtin/commit.c msgid "cannot do a partial commit during a rebase." msgstr "no es pot fer una comissió parcial durant un «rebase»." +#: builtin/commit.c msgid "cannot read the index" msgstr "no es pot llegir l'Ãndex" +#: builtin/commit.c msgid "unable to write temporary index file" msgstr "no s'ha pogut escriure un fitxer d'Ãndex temporal" +#: builtin/commit.c #, c-format msgid "commit '%s' lacks author header" msgstr "a la comissió «%s» li manca la capçalera d'autor" +#: builtin/commit.c #, c-format msgid "commit '%s' has malformed author line" msgstr "la comissió «%s» té una lÃnia d'autor mal formada" +#: builtin/commit.c msgid "malformed --author parameter" msgstr "parà metre --author mal format" +#: builtin/commit.c ident.c #, c-format msgid "invalid date format: %s" msgstr "format de data no và lid: %s" +#: builtin/commit.c msgid "" "unable to select a comment character that is not used\n" "in the current commit message" @@ -4763,74 +5990,88 @@ msgstr "" "no es pot seleccionar un carà cter de comentari que\n" "no sigui usat en el missatge de comissió actual" +#: builtin/commit.c #, c-format msgid "could not lookup commit '%s'" msgstr "no s'ha pogut cercar la comissió «%s»" +#: builtin/commit.c builtin/shortlog.c #, c-format msgid "(reading log message from standard input)\n" msgstr "(s'està llegint el missatge de registre des de l'entrada està ndard)\n" +#: builtin/commit.c msgid "could not read log from standard input" msgstr "no s'ha pogut llegir el registre des de l'entrada està ndard" +#: builtin/commit.c #, c-format msgid "could not read log file '%s'" msgstr "no s'ha pogut llegir el fitxer de registre «%s»" +#: builtin/commit.c #, c-format msgid "options '%s' and '%s:%s' cannot be used together" msgstr "les opcions «%s» i «%s:%s» no es poden usar juntes" +#: builtin/commit.c msgid "could not read SQUASH_MSG" msgstr "no s'ha pogut llegir SQUASH_MSG" +#: builtin/commit.c msgid "could not read MERGE_MSG" msgstr "no s'ha pogut llegir MERGE_MSG" +#: builtin/commit.c bundle.c rerere.c sequencer.c #, c-format msgid "could not open '%s'" msgstr "no s'ha pogut obrir «%s»" +#: builtin/commit.c msgid "could not write commit template" msgstr "no s'ha pogut escriure la plantilla de comissió" +#: builtin/commit.c #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '%c' will be ignored.\n" +"with '%s' will be ignored.\n" msgstr "" -"Introduïu el missatge de comissió per als vostres canvis.\n" -"S'ignoraran les lÃnies que comencin amb «%c».\n" +"Introduïu el missatge de comissió per als vostres canvis. \n" +"S'ignoraran les lÃnies que comencin amb «%s».\n" +#: builtin/commit.c #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '%c' will be ignored, and an empty message aborts the commit.\n" +"with '%s' will be ignored, and an empty message aborts the commit.\n" msgstr "" "Introduïu el missatge de comissió dels vostres canvis.\n" -"S'ignoraran les lÃnies que comencin amb «%c». Un missatge de\n" +"S'ignoraran les lÃnies que comencin amb «%s». Un missatge de\n" "comissió buit avorta la comissió.\n" +#: builtin/commit.c #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '%c' will be kept; you may remove them yourself if you want to.\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" msgstr "" "Introduïu el missatge de comissió pels vostres canvis. Es mantindran\n" -"les lÃnies que comencin amb «%c»; podeu eliminar-les si voleu.\n" +"les lÃnies que comencin amb «%s»; podeu eliminar-les vosaltres mateixos\n" +"si voleu.\n" +#: builtin/commit.c #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '%c' will be kept; you may remove them yourself if you want to.\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" "An empty message aborts the commit.\n" msgstr "" "Introduïu el missatge de comissió dels vostres canvis.\n" -"Es mantindran les lÃnies que comencin amb «%c»; podeu eliminar-les " -"vosaltres\n" -"mateixos si voleu. Un missatge buit avorta la comissió.\n" +"Es mantindran les lÃnies que comencin amb «%s»; podeu eliminar-les \n" +"vosaltres mateixos si voleu. Un missatge buit avorta la comissió.\n" +#: builtin/commit.c msgid "" "\n" "It looks like you may be committing a merge.\n" @@ -4844,6 +6085,7 @@ msgstr "" "\tgit update-ref -d MERGE_HEAD\n" "i intenteu-ho de nou.\n" +#: builtin/commit.c msgid "" "\n" "It looks like you may be committing a cherry-pick.\n" @@ -4857,111 +6099,142 @@ msgstr "" "\tgit update-ref -d CHERRY_PICK_HEAD\n" "i intenteu-ho de nou.\n" +#: builtin/commit.c #, c-format msgid "%sAuthor: %.*s <%.*s>" msgstr "%sAutor: %.*s <%.*s>" +#: builtin/commit.c #, c-format msgid "%sDate: %s" msgstr "%sData: %s" +#: builtin/commit.c #, c-format msgid "%sCommitter: %.*s <%.*s>" msgstr "%sComitent: %.*s <%.*s>" +#: builtin/commit.c msgid "Cannot read index" msgstr "No es pot llegir l'Ãndex" +#: builtin/commit.c builtin/tag.c msgid "unable to pass trailers to --trailers" msgstr "no s'han pogut passar els «trailers» a --trailers" +#: builtin/commit.c msgid "Error building trees" msgstr "Error en construir els arbres" +#: builtin/commit.c builtin/tag.c #, c-format msgid "Please supply the message using either -m or -F option.\n" msgstr "Especifiqueu el missatge usant l'opció -m o l'opció -F.\n" +#: builtin/commit.c #, c-format msgid "--author '%s' is not 'Name <email>' and matches no existing author" msgstr "" "--author «%s» no és «Nom <adreça-electrònica>» i no coincideix amb\n" "cap autor existent" +#: builtin/commit.c #, c-format msgid "Invalid ignored mode '%s'" msgstr "Mode d'ignorà ncia no và lid «%s»" +#: builtin/commit.c #, c-format msgid "Invalid untracked files mode '%s'" msgstr "Mode de fitxers no seguits no và lid «%s»" +#: builtin/commit.c msgid "You are in the middle of a merge -- cannot reword." msgstr "Esteu enmig d'una fusió -- no es pot fer «reword»." +#: builtin/commit.c msgid "You are in the middle of a cherry-pick -- cannot reword." msgstr "Esteu enmig d'un «cherry pick» -- no es pot fer «reword»." +#: builtin/commit.c #, c-format msgid "reword option of '%s' and path '%s' cannot be used together" msgstr "les opcions de «reword» «%s» i camà «%s» no es poden usar juntes" +#: builtin/commit.c #, c-format msgid "reword option of '%s' and '%s' cannot be used together" msgstr "les opcions de «reword» «%s» i «%s» no es poden usar juntes" +#: builtin/commit.c msgid "You have nothing to amend." msgstr "No teniu res a esmenar." +#: builtin/commit.c msgid "You are in the middle of a merge -- cannot amend." msgstr "Esteu enmig d'una fusió -- no es pot esmenar." +#: builtin/commit.c msgid "You are in the middle of a cherry-pick -- cannot amend." msgstr "Esteu enmig d'un «cherry pick» -- no es pot esmenar." +#: builtin/commit.c msgid "You are in the middle of a rebase -- cannot amend." msgstr "Esteu enmig d'un «rebase» -- no es pot esmenar." +#: builtin/commit.c msgid "--reset-author can be used only with -C, -c or --amend." msgstr "--reset-author només es pot usar amb -C, -c o --amend." +#: builtin/commit.c #, c-format msgid "unknown option: --fixup=%s:%s" msgstr "opció desconeguda: --fixup=%s:%s" +#: builtin/commit.c #, c-format msgid "paths '%s ...' with -a does not make sense" msgstr "els camins «%s ...» amb -a no tenen sentit" +#: builtin/commit.c msgid "show status concisely" msgstr "mostra l'estat concisament" +#: builtin/commit.c msgid "show branch information" msgstr "mostra la informació de branca" +#: builtin/commit.c msgid "show stash information" msgstr "mostra la informació de «stash»" +#: builtin/commit.c msgid "compute full ahead/behind values" msgstr "calcula els valors complets endavant/darrere" +#: builtin/commit.c msgid "version" msgstr "versió" +#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c msgid "machine-readable output" msgstr "sortida llegible per una mà quina" +#: builtin/commit.c msgid "show status in long format (default)" msgstr "mostra l'estat en format llarg (per defecte)" +#: builtin/commit.c msgid "terminate entries with NUL" msgstr "acaba les entrades amb NUL" +#: builtin/commit.c msgid "show untracked files, optional modes: all, normal, no. (Default: all)" msgstr "" "mostra els fitxers no seguits, modes opcionals: all, normal, no. (Per " "defecte: all)" +#: builtin/commit.c msgid "" "show ignored files, optional modes: traditional, matching, no. (Default: " "traditional)" @@ -4969,9 +6242,11 @@ msgstr "" "mostra els fitxers ignorats, modes opcionals: traditional, matching, no. " "(Per defecte: traditional, matching, no.)" +#: builtin/commit.c parse-options.h msgid "when" msgstr "quan" +#: builtin/commit.c msgid "" "ignore changes to submodules, optional when: all, dirty, untracked. " "(Default: all)" @@ -4979,153 +6254,199 @@ msgstr "" "ignora els canvis als submòduls, opcional quan: all, dirty, untracked. (Per " "defecte: all)" +#: builtin/commit.c msgid "list untracked files in columns" msgstr "mostra els fitxers no seguits en columnes" +#: builtin/commit.c msgid "do not detect renames" msgstr "no detectis canvis de noms" +#: builtin/commit.c msgid "detect renames, optionally set similarity index" msgstr "detecta canvis de noms, i opcionalment estableix un Ãndex de semblança" +#: builtin/commit.c msgid "Unsupported combination of ignored and untracked-files arguments" msgstr "" "No s'admet la combinació d'arguments d'ignorà ncia i de fitxers no seguits" +#: builtin/commit.c msgid "suppress summary after successful commit" msgstr "omet el resum després d'una comissió reeixida" +#: builtin/commit.c msgid "show diff in commit message template" msgstr "mostra la diferència en la plantilla de missatge de comissió" +#: builtin/commit.c msgid "Commit message options" msgstr "Opcions de missatge de comissió" +#: builtin/commit.c builtin/merge.c builtin/tag.c msgid "read message from file" msgstr "llegeix el missatge des d'un fitxer" +#: builtin/commit.c msgid "author" msgstr "autor" +#: builtin/commit.c msgid "override author for commit" msgstr "sobreescriu l'autor de la comissió" +#: builtin/commit.c builtin/gc.c msgid "date" msgstr "data" +#: builtin/commit.c msgid "override date for commit" msgstr "sobreescriu la data de la comissió" +#: builtin/commit.c parse-options.h ref-filter.h msgid "commit" msgstr "comissió" +#: builtin/commit.c msgid "reuse and edit message from specified commit" msgstr "reusa i edita el missatge de la comissió especificada" +#: builtin/commit.c msgid "reuse message from specified commit" msgstr "reusa el missatge de la comissió especificada" #. TRANSLATORS: Leave "[(amend|reword):]" as-is, #. and only translate <commit>. #. +#: builtin/commit.c msgid "[(amend|reword):]commit" msgstr "[(amend|reword):]commit" +#: builtin/commit.c msgid "" "use autosquash formatted message to fixup or amend/reword specified commit" msgstr "" -"usa un missatge amb format de «squash» automà tic per a esmenar la comissió " -"especificada" +"usa un missatge amb format de «squash» automà tic per a fer amend/reword de " +"la comissió especificada" +#: builtin/commit.c msgid "use autosquash formatted message to squash specified commit" msgstr "" "usa un missatge amb format de «squash» automà tic per a fer «squash» de la " "comissió especificada" +#: builtin/commit.c msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "l'autor de la comissió soc jo ara (s'usa amb -C/-c/--amend)" +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c msgid "trailer" msgstr "remolc" +#: builtin/commit.c builtin/tag.c msgid "add custom trailer(s)" msgstr "afegeix un «trailer» personalitzat" +#: builtin/commit.c builtin/log.c builtin/merge.c builtin/pull.c +#: builtin/revert.c msgid "add a Signed-off-by trailer" msgstr "afegeix un «trailer» tipus «Signed-off-by»" +#: builtin/commit.c msgid "use specified template file" msgstr "usa el fitxer de plantilla especificat" +#: builtin/commit.c msgid "force edit of commit" msgstr "força l'edició de la comissió" +#: builtin/commit.c msgid "include status in commit message template" msgstr "inclou l'estat en la plantilla de missatge de comissió" +#: builtin/commit.c msgid "Commit contents options" msgstr "Opcions per al contingut de les comissions" +#: builtin/commit.c msgid "commit all changed files" msgstr "comet tots els fitxers canviats" +#: builtin/commit.c msgid "add specified files to index for commit" msgstr "afegeix els fitxers especificats a l'Ãndex per a cometre" +#: builtin/commit.c msgid "interactively add files" msgstr "afegeix els fitxers interactivament" +#: builtin/commit.c msgid "interactively add changes" msgstr "afegeix els canvis interactivament" +#: builtin/commit.c msgid "commit only specified files" msgstr "comet només els fitxers especificats" +#: builtin/commit.c msgid "bypass pre-commit and commit-msg hooks" msgstr "evita els lligams de precomissió i missatge de comissió" +#: builtin/commit.c msgid "show what would be committed" msgstr "mostra què es cometria" +#: builtin/commit.c msgid "amend previous commit" msgstr "esmena la comissió anterior" +#: builtin/commit.c msgid "bypass post-rewrite hook" msgstr "evita el lligam de post escriptura" +#: builtin/commit.c msgid "ok to record an empty change" msgstr "està bé registrar un canvi buit" +#: builtin/commit.c msgid "ok to record a change with an empty message" msgstr "està bé registrar un canvi amb missatge buit" +#: builtin/commit.c sequencer.c msgid "could not parse HEAD commit" msgstr "no s'ha pogut analitzar la comissió HEAD" +#: builtin/commit.c #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Fitxer MERGE_HEAD malmès (%s)" +#: builtin/commit.c msgid "could not read MERGE_MODE" msgstr "no s'ha pogut llegir MERGE_MODE" +#: builtin/commit.c #, c-format msgid "could not read commit message: %s" msgstr "no s'ha pogut llegir el missatge de comissió: %s" +#: builtin/commit.c #, c-format msgid "Aborting commit due to empty commit message.\n" msgstr "S'està avortant la comissió a causa d'un missatge de comissió buit.\n" +#: builtin/commit.c #, c-format msgid "Aborting commit; you did not edit the message.\n" msgstr "S'està avortant la comissió; no heu editat el missatge.\n" +#: builtin/commit.c #, c-format msgid "Aborting commit due to empty commit message body.\n" msgstr "" "S'està interrompent la comissió a causa d'un missatge de comissió buit.\n" +#: builtin/commit.c msgid "" "repository has been updated, but unable to write\n" "new index file. Check that disk is not full and quota is\n" @@ -5136,183 +6457,230 @@ msgstr "" "la quota no s'ha excedit, i després feu «git restore --staged :/n»\n" "per a recuperar-ho." -msgid "git config [<options>]" -msgstr "git config [<opcions>]" +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<opció-fitxer>] [<opció-presentació>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "argument --type no reconegut, %s" +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<opció-fitxer>] [<opció-presentació>] [--includes] [--all] " +"[--regexp] [--value=<valor>] [--fixed-value] [--default=<default>] <nom>" -msgid "only one type at a time" -msgstr "només un tipus cada cop" +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<opció-fitxer>] [--type=<tipus>] [--all] [--value=<valor>] " +"[--fixed-value] <nom> <valor>" +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<opció-fitxer>] [--all] [--value=<valor>] [--fixed-value] " +"<name> <valor>" + +#: builtin/config.c +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<opció-fitxer>] <nom-vell> <nom-nou>" + +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<opció-fitxer>] <nom>" + +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "git config edit [<file-option>]" +msgstr "git config edit [<opció-fitxer>]" + +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<opció-fitxer>] --get-colorbool <nom> [<stdout-is-tty>]" + +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<opció-fitxer>] [<opció-presentació>] [--includes] [--all] " +"[--regexp=<expr-reg>] [--value=<valor>] [--fixed-value] [--" +"default=<default>] <nom>" + +# Cal traduir els parà metres amb <...>? +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<opció-fitxer>] [--type=<tipus>] [--comment=<missatge>] [--" +"all] [--value=<valor>] [--fixed-value] <nom> <valor>" + +#: builtin/config.c msgid "Config file location" msgstr "Ubicació del fitxer de configuració" +#: builtin/config.c msgid "use global config file" msgstr "usa el fitxer de configuració global" +#: builtin/config.c msgid "use system config file" msgstr "usa el fitxer de configuració del sistema" +#: builtin/config.c msgid "use repository config file" msgstr "usa el fitxer de configuració del repositori" +#: builtin/config.c msgid "use per-worktree config file" msgstr "usa un fitxer de configuració per repositori" +#: builtin/config.c builtin/gc.c msgid "use given config file" msgstr "usa el fitxer de configuració donat" +#: builtin/config.c msgid "blob-id" msgstr "ID de blob" +#: builtin/config.c msgid "read config from given blob object" msgstr "llegeix la configuració de l'objecte de blob donat" -msgid "Action" -msgstr "Acció" - -msgid "get value: name [value-pattern]" -msgstr "obtén valor: nom [value-pattern]" - -msgid "get all values: key [value-pattern]" -msgstr "obtén tots els valors: clau [value-pattern]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "obtén valors de regexp: name-regex [value-pattern]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "obtén el valor especÃfic per a l'URL: secció[.variable] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "" -"reemplaça totes les variables que coincideixen: nom valor [value-pattern]" - -msgid "add a new variable: name value" -msgstr "afegeix una variable nova: nom valor" - -msgid "remove a variable: name [value-pattern]" -msgstr "elimina una variable: nom [value-pattern]" - -msgid "remove all matches: name [value-pattern]" -msgstr "elimina totes les coincidències: nom [value-pattern]" - -msgid "rename section: old-name new-name" -msgstr "canvia el nom de secció: nom-antic nom-nou" - -msgid "remove a section: name" -msgstr "elimina una secció: nom" - -msgid "list all" -msgstr "llista'ls tots" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "" -"usa la igualtat de les cadenes quan es comparen els valors amb «value-" -"pattern»" - -msgid "open an editor" -msgstr "obre un editor" - -msgid "find the color configured: slot [default]" -msgstr "troba el color configurat: ranura [per defecte]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "troba el parà metre de color: ranura [stdout-és-tty]" - +#: builtin/config.c msgid "Type" msgstr "Tipus" +#: builtin/config.c builtin/hash-object.c msgid "type" msgstr "tipus" +#: builtin/config.c msgid "value is given this type" msgstr "el valor és d'aquest tipus que s'ha donat" +#: builtin/config.c msgid "value is \"true\" or \"false\"" msgstr "el valor és «true» o «false»" +#: builtin/config.c msgid "value is decimal number" msgstr "el valor és un nombre decimal" +#: builtin/config.c msgid "value is --bool or --int" msgstr "el valor és --bool o --int" +#: builtin/config.c msgid "value is --bool or string" msgstr "el valor és --bool o string" +#: builtin/config.c msgid "value is a path (file or directory name)" msgstr "el valor és un camà (nom de fitxer o directori)" +#: builtin/config.c msgid "value is an expiry date" msgstr "el valor és una data de venciment" -msgid "Other" -msgstr "Altre" +#: builtin/config.c +msgid "Display options" +msgstr "Opcions de visualització" +#: builtin/config.c msgid "terminate values with NUL byte" msgstr "acaba els valors amb un octet NUL" +#: builtin/config.c msgid "show variable names only" msgstr "mostra només els noms de variable" -msgid "respect include directives on lookup" -msgstr "respecta les directives d'inclusió en cercar" - +#: builtin/config.c msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "mostra l'origen de la configuració (fitxer, entrada està ndard, blob, lÃnia " "d'ordres)" +#: builtin/config.c msgid "show scope of config (worktree, local, global, system, command)" msgstr "" "mostra l'abast de la configuració («worktree», «local», «global», «system», " "«command»)" -msgid "value" -msgstr "valor" +#: builtin/config.c +msgid "show config keys in addition to their values" +msgstr "mostra les claus de configuració a més dels seus valors" -msgid "with --get, use default value when missing entry" -msgstr "amb --get utilitza el valor per defecte quan falti una entrada" +#: builtin/config.c +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "argument --type no reconegut, %s" + +#: builtin/config.c +msgid "only one type at a time" +msgstr "només un tipus cada cop" +#: builtin/config.c #, c-format msgid "wrong number of arguments, should be %d" msgstr "nombre d'arguments erroni, ha de ser %d" +#: builtin/config.c #, c-format msgid "wrong number of arguments, should be from %d to %d" msgstr "nombre d'arguments erroni, ha de ser %d a %d" +#: builtin/config.c #, c-format msgid "invalid key pattern: %s" msgstr "patró de la clau no và lid: %s" +#: builtin/config.c config.c #, c-format msgid "invalid pattern: %s" msgstr "patró no và lid: %s" +#: builtin/config.c #, c-format msgid "failed to format default config value: %s" msgstr "" "s'ha produït un error en formatar el valor per defecte de la configuració: %s" +#: builtin/config.c #, c-format msgid "cannot parse color '%s'" msgstr "no es pot analitzar el color «%s»" +#: builtin/config.c msgid "unable to parse default color value" msgstr "no s'ha pogut analitzar el valor de color per defecte" +#: builtin/config.c msgid "not in a git directory" msgstr "no és en un directori git" +#: builtin/config.c msgid "writing to stdin is not supported" msgstr "no s'admet escriure a stdin" +#: builtin/config.c msgid "writing config blobs is not supported" msgstr "no s'admet l'escriptura de blobs de configuració" +#: builtin/config.c #, c-format msgid "" "# This is Git's per-user configuration file.\n" @@ -5327,21 +6695,27 @@ msgstr "" "#\tname = %s\n" "#\temail = %s\n" +#: builtin/config.c msgid "only one config file at a time" msgstr "només un fitxer de configuració cada cop" +#: builtin/config.c msgid "--local can only be used inside a git repository" msgstr "--local només es pot usar dins d'un repositori git" +#: builtin/config.c msgid "--blob can only be used inside a git repository" msgstr "--blob només es pot usar dins d'un repositori git" +#: builtin/config.c msgid "--worktree can only be used inside a git repository" msgstr "--worktree només es pot usar dins d'un repositori git" +#: builtin/config.c builtin/gc.c msgid "$HOME not set" msgstr "$HOME no està establerta" +#: builtin/config.c msgid "" "--worktree cannot be used with multiple working trees unless the config\n" "extension worktreeConfig is enabled. Please read \"CONFIGURATION FILE\"\n" @@ -5351,44 +6725,102 @@ msgstr "" "l'extensió de configuració worktreeConfig estigui habilitada. Llegiu la " "secció «CONFIGURATION FILE» a «git help worktree» per a més detalls" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color i el tipus de variable són incoherents" +#: builtin/config.c +msgid "Other" +msgstr "Altre" -msgid "only one action at a time" -msgstr "només una acció cada cop" +#: builtin/config.c +msgid "respect include directives on lookup" +msgstr "respecta les directives d'inclusió en cercar" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only només és aplicable a --list o --get-regexp" +#: builtin/config.c +#, c-format +msgid "unable to read config file '%s'" +msgstr "no s'ha pogut llegir el fitxer de configuració «%s»" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" +#: builtin/config.c +msgid "error processing config file(s)" +msgstr "s'ha produït un error en processar els fitxers de configuració" + +#: builtin/config.c +msgid "Filter options" +msgstr "Opcions de filtre" + +# multi-valued → multivalor? +#: builtin/config.c +msgid "return all values for multi-valued config options" +msgstr "retorna tots els valors per a les opcions de configuració multivalor" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "interpreta el nom com una expressió regular" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "mostra la configuració amb els valors coincidents amb el patró" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" msgstr "" -"--show-origin només és aplicable a --get, --get-all, --get-regexp, i --list" +"usa la igualtat de cadenes quan es comparen els valors amb el patró de valor" -msgid "--default is only applicable to --get" -msgstr "--default només és aplicable a --get" +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "mostra la configuració coincident amb l'URL indicat" + +#: builtin/config.c +msgid "value" +msgstr "valor" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "utilitza el valor per defecte quan falti una entrada" +#: builtin/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value només s'aplica amb «value-pattern»" -#, c-format -msgid "unable to read config file '%s'" -msgstr "no s'ha pogut llegir el fitxer de configuració «%s»" +#: builtin/config.c +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= no es pot utilitzar amb --all o --url=" -msgid "error processing config file(s)" -msgstr "s'ha produït un error en processar els fitxers de configuració" +#: builtin/config.c +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= no es pot usar amb --all, --regexp o --value" -msgid "editing stdin is not supported" -msgstr "no hi ha compatibilitat per a l'edició a stdin" +#: builtin/config.c +msgid "Filter" +msgstr "Filtra" -msgid "editing blobs is not supported" -msgstr "no hi ha compatibilitat per l'edició de blobs" +# multi-valued → multivalor? +#: builtin/config.c +msgid "replace multi-valued config option with new value" +msgstr "reemplaça l'opció de configuració multivalor amb el valor nou" -#, c-format -msgid "cannot create configuration file %s" -msgstr "no es pot crear el fitxer de configuració %s" +#: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"cadena de comentari llegible per humans (es farà que comence per\n" +"# si cal)" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "afegeix una lÃnia nova sense alterar cap dels valors existents" + +# only applies → només funciona? +#: builtin/config.c +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value només s'aplica amb --value=<patró>" +#: builtin/config.c +msgid "--append cannot be used with --value=<pattern>" +msgstr "no es pot utilitzar --append amb --value=<patró>" + +#: builtin/config.c #, c-format msgid "" "cannot overwrite multiple values with a single value\n" @@ -5397,13 +6829,128 @@ msgstr "" "no es poden sobreescriure múltiples valors amb un sol valor\n" " Useu una expressió regular, --add o --replace-all per a canviar %s." +#: builtin/config.c #, c-format msgid "no such section: %s" msgstr "no existeix la secció: %s" +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "no hi ha compatibilitat per a l'edició a stdin" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "no hi ha compatibilitat per l'edició de blobs" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "no es pot crear el fitxer de configuració %s" + +#: builtin/config.c +msgid "Action" +msgstr "Acció" + +#: builtin/config.c +msgid "get value: name [<value-pattern>]" +msgstr "get value: nom [<patró-valors>]" + +#: builtin/config.c +msgid "get all values: key [<value-pattern>]" +msgstr "obté tots els valors: clau [<patró-valors>]" + +# he traduit el nom del parà metre +#: builtin/config.c +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "" +"obté els valors per a l'expressió regular: expressio-regular-nom [<patró-" +"valors>]" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "obtén el valor especÃfic per a l'URL: secció[.variable] URL" + +# he traduït els noms dels parà metres +#: builtin/config.c +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "" +"reemplaça totes les variables que coincideixin: nom valor [<patró-valors>]" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "afegeix una variable nova: nom valor" + +# cal traduir name? +#: builtin/config.c +msgid "remove a variable: name [<value-pattern>]" +msgstr "elimina una variable: nom [<patró-valors>]" + +#: builtin/config.c +msgid "remove all matches: name [<value-pattern>]" +msgstr "elimina totes les coincidències: nom [<patró-valors>]" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "canvia el nom de secció: nom-antic nom-nou" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "elimina una secció: nom" + +#: builtin/config.c +msgid "list all" +msgstr "llista'ls tots" + +#: builtin/config.c +msgid "open an editor" +msgstr "obre un editor" + +# slot → ??? ; <default> → ??? +#: builtin/config.c +msgid "find the color configured: slot [<default>]" +msgstr "troba el color configurat: slot [<default>]" + +#: builtin/config.c +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "troba la configuració de color: slot [<stdout-is-tty>]" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "amb --get utilitza el valor per defecte quan falti una entrada" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "--get-color i el tipus de variable són incoherents" + +#: builtin/config.c +msgid "no action specified" +msgstr "no s'ha especificat cap acció" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only només és aplicable a --list o --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin només és aplicable a --get, --get-all, --get-regexp, i --list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "--default només és aplicable a --get" + +# add/set/replace sense traduir, entenc +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment només es pot aplicar a operacions add/set/replace" + +#: builtin/count-objects.c msgid "print sizes in human readable format" msgstr "imprimeix les mides en un format llegible pels humans" +#: builtin/credential-cache--daemon.c #, c-format msgid "" "The permissions on your socket directory are too loose; other\n" @@ -5417,67 +6964,83 @@ msgstr "" "\n" "\tchmod 0700 %s" +#: builtin/credential-cache--daemon.c msgid "print debugging messages to stderr" msgstr "imprimeix els missatges de depuració a stderr" +#: builtin/credential-cache--daemon.c msgid "credential-cache--daemon unavailable; no unix socket support" msgstr "" "credential-cache--daemon no disponible; no hi ha compatibilitat amb sòcols " "d'unix" +#: builtin/credential-cache.c msgid "credential-cache unavailable; no unix socket support" msgstr "" "credencial-cache no disponible; no hi ha compatibilitat amb els sòcols d'unix" +#: builtin/credential-store.c #, c-format msgid "unable to get credential storage lock in %d ms" msgstr "" "no s'ha pogut obtenir el bloqueig de l'emmagatzematge de credencials en %d ms" +#: builtin/describe.c msgid "" "git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" msgstr "" "git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" +#: builtin/describe.c msgid "" "git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" msgstr "" "git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" +#: builtin/describe.c msgid "git describe <blob>" msgstr "git describe <blob>" +#: builtin/describe.c msgid "head" msgstr "davant per" +#: builtin/describe.c msgid "lightweight" msgstr "lleuger" +#: builtin/describe.c msgid "annotated" msgstr "anotat" +#: builtin/describe.c #, c-format msgid "annotated tag %s not available" msgstr "l'etiqueta anotada %s no és disponible" +#: builtin/describe.c #, c-format msgid "tag '%s' is externally known as '%s'" msgstr "l'etiqueta «%s» es coneix externament com a «%s»" +#: builtin/describe.c #, c-format msgid "no tag exactly matches '%s'" msgstr "cap etiqueta coincideix exactament amb «%s»" +#: builtin/describe.c #, c-format msgid "No exact match on refs or tags, searching to describe\n" msgstr "" "No hi ha cap coincidència exacta en la cerca de referències o etiquetes per " "a descriure\n" +#: builtin/describe.c #, c-format msgid "finished search at %s\n" msgstr "s'ha finalitzat la cerca a %s\n" +#: builtin/describe.c #, c-format msgid "" "No annotated tags can describe '%s'.\n" @@ -5486,6 +7049,7 @@ msgstr "" "Cap etiqueta anotada pot descriure «%s».\n" "No obstant això, hi havia etiquetes no anotades: proveu --tags." +#: builtin/describe.c #, c-format msgid "" "No tags can describe '%s'.\n" @@ -5494,10 +7058,12 @@ msgstr "" "Cap etiqueta pot descriure «%s».\n" "Proveu --always, o creeu algunes etiquetes." +#: builtin/describe.c #, c-format msgid "traversed %lu commits\n" msgstr "%lu comissions recorregudes\n" +#: builtin/describe.c #, c-format msgid "" "more than %i tags found; listed %i most recent\n" @@ -5506,67 +7072,87 @@ msgstr "" "s'han trobat més de %i etiquetes: s'han llistat les %i més recents\n" "s'ha renunciat la cerca a %s\n" +#: builtin/describe.c #, c-format msgid "describe %s\n" msgstr "descriu %s\n" +#: builtin/describe.c #, c-format msgid "Not a valid object name %s" msgstr "%s no és un nom d'objecte và lid" +#: builtin/describe.c #, c-format msgid "%s is neither a commit nor blob" msgstr "%s no és una comissió o un blob" +#: builtin/describe.c msgid "find the tag that comes after the commit" msgstr "troba l'etiqueta que vingui després de la comissió" +#: builtin/describe.c msgid "debug search strategy on stderr" msgstr "estratègia de cerca de depuració en stderr" +#: builtin/describe.c msgid "use any ref" msgstr "usa qualsevol referència" +#: builtin/describe.c msgid "use any tag, even unannotated" msgstr "usa qualsevol etiqueta, fins i tot aquelles sense anotar" +#: builtin/describe.c msgid "always use long format" msgstr "sempre usa el format llarg" +#: builtin/describe.c msgid "only follow first parent" msgstr "només segueix el primer pare" +#: builtin/describe.c msgid "only output exact matches" msgstr "emet només coincidències exactes" +#: builtin/describe.c msgid "consider <n> most recent tags (default: 10)" msgstr "considera les <n> etiquetes més recents (per defecte: 10)" +#: builtin/describe.c msgid "only consider tags matching <pattern>" msgstr "només considera les etiquetes que coincideixen amb <patró>" +#: builtin/describe.c msgid "do not consider tags matching <pattern>" msgstr "no consideris les etiquetes que no coincideixen amb <patró>" +#: builtin/describe.c builtin/name-rev.c msgid "show abbreviated commit object as fallback" msgstr "mostra l'objecte de comissió abreviat com a sistema alternatiu" +#: builtin/describe.c msgid "mark" msgstr "marca" +#: builtin/describe.c msgid "append <mark> on dirty working tree (default: \"-dirty\")" msgstr "annexa <marca> en l'arbre de treball brut (per defecte: «-dirty»)" +#: builtin/describe.c msgid "append <mark> on broken working tree (default: \"-broken\")" msgstr "annexa <marca> en l'arbre de treball brut (per defecte: «-broken»)" +#: builtin/describe.c msgid "No names found, cannot describe anything." msgstr "No s'ha trobat cap nom, no es pot descriure res." +#: builtin/describe.c #, c-format msgid "option '%s' and commit-ishes cannot be used together" msgstr "opció «%s» i les de comissió no es poden usar juntes" +#: builtin/diagnose.c msgid "" "git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n" " [--mode=<mode>]" @@ -5574,67 +7160,85 @@ msgstr "" "git diagnose [(-o | --output-directory) <camÃ>] [(-s | --suffix) <format>]\n" " [--mode=<mode>]" +#: builtin/diagnose.c msgid "specify a destination for the diagnostics archive" msgstr "especifiqueu una destinació per a l'arxiu de diagnòstic" +#: builtin/diagnose.c msgid "specify a strftime format suffix for the filename" msgstr "especifiqueu un sufix en format strftime per al nom de fitxer" +#: builtin/diagnose.c msgid "specify the content of the diagnostic archive" msgstr "especifica el contingut de l'arxiu de diagnòstic" +#: builtin/diff-tree.c msgid "--merge-base only works with two commits" msgstr "--merge-base només funciona amb dues comissions" +#: builtin/diff.c #, c-format msgid "'%s': not a regular file or symlink" msgstr "«%s»: no és ni fitxer regular ni enllaç simbòlic" +#: builtin/diff.c msgid "no merge given, only parents." msgstr "no s'ha donat cap fusió, només els pares." +#: builtin/diff.c #, c-format msgid "invalid option: %s" msgstr "opció no và lida: %s" +#: builtin/diff.c #, c-format msgid "%s...%s: no merge base" msgstr "%s...%s: sense una base de fusió" +#: builtin/diff.c msgid "Not a git repository" msgstr "No és un repositori de git" +#: builtin/diff.c builtin/grep.c #, c-format msgid "invalid object '%s' given." msgstr "s'ha donat un objecte no và lid «%s»." +#: builtin/diff.c #, c-format msgid "more than two blobs given: '%s'" msgstr "s'ha donat més de dos blobs: «%s»" +#: builtin/diff.c #, c-format msgid "unhandled object '%s' given." msgstr "s'ha donat l'objecte no gestionat «%s»." +#: builtin/diff.c #, c-format msgid "%s...%s: multiple merge bases, using %s" msgstr "%s...%s: múltiples bases de fusió, utilitzant %s" +#: builtin/difftool.c msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]" msgstr "git difftool [<opcions>] [<comissió> [<comissió>]] [--] [<camÃ>...]" +#: builtin/difftool.c #, c-format msgid "could not read symlink %s" msgstr "no s'ha pogut llegir l'enllaç simbòlic %s" +#: builtin/difftool.c #, c-format msgid "could not read symlink file %s" msgstr "no s'ha pogut llegir el fitxer d'enllaç simbòlic %s" +#: builtin/difftool.c #, c-format msgid "could not read object %s for symlink %s" msgstr "no es pot llegir l'objecte %s per l'enllaç simbòlic %s" +#: builtin/difftool.c msgid "" "combined diff formats ('-c' and '--cc') are not supported in\n" "directory diff mode ('-d' and '--dir-diff')." @@ -5642,50 +7246,64 @@ msgstr "" "els formats de diff combinats («-c» i «--cc») no s'admeten\n" "en el mode diff de directoris («-d» i «--dir-diff»)." +#: builtin/difftool.c #, c-format msgid "both files modified: '%s' and '%s'." msgstr "s'han modificat ambdós fitxers: «%s» i «%s»." +#: builtin/difftool.c msgid "working tree file has been left." msgstr "s'ha deixat un fitxer de l'arbre de treball." +#: builtin/difftool.c sequencer.c #, c-format msgid "could not copy '%s' to '%s'" msgstr "no s'ha pogut copiar «%s» a «%s»" +#: builtin/difftool.c #, c-format msgid "temporary files exist in '%s'." msgstr "existeix un fitxer temporal a «%s»." +#: builtin/difftool.c msgid "you may want to cleanup or recover these." msgstr "podeu netejar o recuperar-los." +#: builtin/difftool.c #, c-format msgid "failed: %d" msgstr "ha fallat: %d" +#: builtin/difftool.c msgid "use `diff.guitool` instead of `diff.tool`" msgstr "usa «diff.guitool» en lloc de «diff.tool»" +#: builtin/difftool.c msgid "perform a full-directory diff" msgstr "fes un diff de tot el directori" +#: builtin/difftool.c msgid "do not prompt before launching a diff tool" msgstr "no preguntis abans d'executar l'eina diff" +#: builtin/difftool.c msgid "use symlinks in dir-diff mode" msgstr "utilitza enllaços simbòlics en mode dir-diff" +#: builtin/difftool.c msgid "tool" msgstr "eina" +#: builtin/difftool.c msgid "use the specified diff tool" msgstr "utilitza l'eina de diff especificada" +#: builtin/difftool.c msgid "print a list of diff tools that may be used with `--tool`" msgstr "" "imprimeix una llista de totes les eines diff que podeu usar amb «--tool»" +#: builtin/difftool.c msgid "" "make 'git-difftool' exit when an invoked diff tool returns a non-zero exit " "code" @@ -5693,187 +7311,241 @@ msgstr "" "fes que «git-difftool» surti quan l'eina de diff invocada torna un codi de " "sortida diferent de zero" +#: builtin/difftool.c msgid "specify a custom command for viewing diffs" msgstr "especifiqueu una ordre personalitzada per a veure diffs" +#: builtin/difftool.c msgid "passed to `diff`" msgstr "passa-ho a «diff»" +#: builtin/difftool.c msgid "difftool requires worktree or --no-index" msgstr "difftool requereix worktree o --no-index" +#: builtin/difftool.c msgid "no <tool> given for --tool=<tool>" msgstr "no s'ha proporcionat l'<eina> per a --tool=<eina>" +#: builtin/difftool.c msgid "no <cmd> given for --extcmd=<cmd>" msgstr "no s'ha proporcionat l'<ordre> per a --extcmd=<ordre>" +#: builtin/fast-export.c msgid "git fast-export [<rev-list-opts>]" msgstr "git fast-export [<rev-list-opts>]" +#: builtin/fast-export.c msgid "Error: Cannot export nested tags unless --mark-tags is specified." msgstr "" "Error: no es poden exportar les etiquetes imbricades a menys que " "s'especifiqui --mark-tags." +#: builtin/fast-export.c msgid "--anonymize-map token cannot be empty" msgstr "el testimoni de --anonymize-map no pot estar buit" +#: builtin/fast-export.c msgid "show progress after <n> objects" msgstr "mostra el progrés després de <n> objectes" +#: builtin/fast-export.c msgid "select handling of signed tags" msgstr "selecciona la gestió de les etiquetes signades" +#: builtin/fast-export.c msgid "select handling of tags that tag filtered objects" msgstr "selecciona la gestió de les etiquetes que etiquetin objectes filtrats" +#: builtin/fast-export.c msgid "select handling of commit messages in an alternate encoding" msgstr "" "selecciona la gestió dels missatges de comissió en una codificació " "alternativa" +#: builtin/fast-export.c msgid "dump marks to this file" msgstr "bolca les marques a aquest fitxer" +#: builtin/fast-export.c msgid "import marks from this file" msgstr "importa les marques d'aquest fitxer" +#: builtin/fast-export.c msgid "import marks from this file if it exists" msgstr "importa marques d'aquest fitxer si existeix" +#: builtin/fast-export.c msgid "fake a tagger when tags lack one" msgstr "fingeix un etiquetador quan en falti un a les etiquetes" +#: builtin/fast-export.c msgid "output full tree for each commit" msgstr "imprimeix l'arbre complet de per a cada comissió" +#: builtin/fast-export.c msgid "use the done feature to terminate the stream" msgstr "usa la caracterÃstica fet per a acabar el flux" +#: builtin/fast-export.c msgid "skip output of blob data" msgstr "omet la sortida de dades de blob" +#: builtin/fast-export.c builtin/log.c msgid "refspec" msgstr "especificació de referència" +#: builtin/fast-export.c msgid "apply refspec to exported refs" msgstr "aplica l'especificació de referència a les referències exportades" +#: builtin/fast-export.c msgid "anonymize output" msgstr "anonimitza la sortida" +#: builtin/fast-export.c msgid "from:to" msgstr "des de:a" +#: builtin/fast-export.c msgid "convert <from> to <to> in anonymized output" msgstr "converteix <from> a <to> en una sortida anònima" +#: builtin/fast-export.c msgid "reference parents which are not in fast-export stream by object id" msgstr "" "referència els pares que no estan en flux d'exportació rà pida per " "identificador d'objecte" +#: builtin/fast-export.c msgid "show original object ids of blobs/commits" msgstr "mostra els ID dels objectes originals dels blobs i comissions" +#: builtin/fast-export.c msgid "label tags with mark ids" msgstr "marca les etiquetes amb els identificadors de marca" +#: builtin/fast-import.c #, c-format msgid "Missing from marks for submodule '%s'" msgstr "Falten les marques «from» per al submòdul «%s»" +#: builtin/fast-import.c #, c-format msgid "Missing to marks for submodule '%s'" msgstr "Falten les marques per al submòdul «%s»" +#: builtin/fast-import.c #, c-format msgid "Expected 'mark' command, got %s" msgstr "S'esperava l'ordre «mark», s'ha rebut %s" +#: builtin/fast-import.c #, c-format msgid "Expected 'to' command, got %s" msgstr "S'esperava l'ordre «to», s'ha rebut «%s»" +#: builtin/fast-import.c msgid "Expected format name:filename for submodule rewrite option" msgstr "" "S'esperava el format «nom:nom de fitxer» per a l'opció de reescriptura de " "submòdul" +#: builtin/fast-import.c #, c-format msgid "feature '%s' forbidden in input without --allow-unsafe-features" msgstr "" "caracterÃstica «%s» prohibida a l'entrada sense --allow-unsafe-features" +#: builtin/fetch-pack.c #, c-format msgid "Lockfile created but not reported: %s" msgstr "S'ha creat el fitxer de bloqueig però no s'ha informat: %s" +#: builtin/fetch.c msgid "git fetch [<options>] [<repository> [<refspec>...]]" -msgstr "" -"git fetch [<opcions>] [<repositori> [<especificació-de-referència>...]]" +msgstr "git fetch [<opcions>] [<repositori> [<especificació-referència>...]]" +#: builtin/fetch.c msgid "git fetch [<options>] <group>" msgstr "git fetch [<opcions>] <grup>" +#: builtin/fetch.c msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]" msgstr "git fetch --multiple [<opcions>] [(<repositori> | <grup>)...]" +#: builtin/fetch.c msgid "git fetch --all [<options>]" msgstr "git fetch --all [<opcions>]" +#: builtin/fetch.c msgid "fetch.parallel cannot be negative" msgstr "fetch.parallel no pot ser negatiu" +#: builtin/fetch.c msgid "couldn't find remote ref HEAD" msgstr "no s'ha pogut trobar la referència HEAD remota" +#: builtin/fetch.c #, c-format msgid "From %.*s\n" msgstr "De %.*s\n" +#: builtin/fetch.c #, c-format msgid "object %s not found" msgstr "objecte %s no trobat" +#: builtin/fetch.c msgid "[up to date]" msgstr "[al dia]" +#: builtin/fetch.c msgid "[rejected]" msgstr "[rebutjat]" +#: builtin/fetch.c msgid "can't fetch into checked-out branch" msgstr "no es pot obtenir en la branca actual" +#: builtin/fetch.c msgid "[tag update]" msgstr "[actualització d'etiqueta]" +#: builtin/fetch.c msgid "unable to update local ref" msgstr "no s'ha pogut actualitzar la referència local" +#: builtin/fetch.c msgid "would clobber existing tag" msgstr "s'adjuntaria l'etiqueta existent" +#: builtin/fetch.c msgid "[new tag]" msgstr "[etiqueta nova]" +#: builtin/fetch.c msgid "[new branch]" msgstr "[branca nova]" +#: builtin/fetch.c msgid "[new ref]" msgstr "[referència nova]" +#: builtin/fetch.c msgid "forced update" msgstr "actualització forçada" +#: builtin/fetch.c msgid "non-fast-forward" msgstr "sense avanç rà pid" +#: builtin/fetch.c builtin/grep.c sequencer.c #, c-format msgid "cannot open '%s'" msgstr "no es pot obrir «%s»" +#: builtin/fetch.c msgid "" "fetch normally indicates which branches had a forced update,\n" "but that check has been disabled; to re-enable, use '--show-forced-updates'\n" @@ -5885,6 +7557,7 @@ msgstr "" "utilitzeu\n" "«--show-forced-updates» o executeu «git config fetch.showForcedUpdates true»" +#: builtin/fetch.c #, c-format msgid "" "it took %.2f seconds to check forced updates; you can use\n" @@ -5896,15 +7569,18 @@ msgstr "" "utilitzar «--no-show-forced-updates» o executar «git config \n" "fetch.showForcedUpdates false» per a evitar aquesta comprovació.\n" +#: builtin/fetch.c #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s no ha enviat tots els objectes necessaris\n" +msgid "%s did not send all necessary objects" +msgstr "%s no ha enviat tot els objectes necessaris" +#: builtin/fetch.c #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" msgstr "" "s'ha rebutjat %s perquè no es permeten actualitzar les arrels superficials" +#: builtin/fetch.c #, c-format msgid "" "some local refs could not be updated; try running\n" @@ -5914,43 +7590,54 @@ msgstr "" " intenteu executar «git remote prune %s» per a eliminar\n" " qualsevol branca antiga o conflictiva" +#: builtin/fetch.c #, c-format msgid " (%s will become dangling)" -msgstr " (%s es tornarà penjant)" +msgstr " (%s es tornarà despenjat)" +#: builtin/fetch.c #, c-format msgid " (%s has become dangling)" -msgstr " (%s s'ha tornat penjant)" +msgstr " (%s s'ha quedat despenjat)" +#: builtin/fetch.c msgid "[deleted]" msgstr "[suprimit]" +#: builtin/fetch.c builtin/remote.c msgid "(none)" msgstr "(cap)" +#: builtin/fetch.c #, c-format msgid "refusing to fetch into branch '%s' checked out at '%s'" msgstr "s'ha rebutjat l'obtenció en la branca «%s» agafada a «%s»" +#: builtin/fetch.c #, c-format msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "l'opció «%s» amb valor «%s» no és và lida per a %s" +#: builtin/fetch.c #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "s'ignora l'opció «%s» per a %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "l'opció «%s» s'ignora per a «%s»" +#: builtin/fetch.c object-file.c #, c-format msgid "%s is not a valid object" msgstr "%s no és un objecte và lid" +#: builtin/fetch.c #, c-format msgid "the object %s does not exist" msgstr "l'objecte %s no existeix" +#: builtin/fetch.c msgid "multiple branches detected, incompatible with --set-upstream" msgstr "s'han detectat múltiples branques, incompatible amb --set-upstream" +#: builtin/fetch.c #, c-format msgid "" "could not set upstream of HEAD to '%s' from '%s' when it does not point to " @@ -5959,16 +7646,20 @@ msgstr "" "no s'ha pogut establir la font de HEAD a «%s» des de «%s» quan no assenyala " "cap branca." +#: builtin/fetch.c msgid "not setting upstream for a remote remote-tracking branch" msgstr "" "no s'està configurant la font per a una branca remota amb seguiment remot" +#: builtin/fetch.c msgid "not setting upstream for a remote tag" msgstr "no s'està configurant la font d'una etiqueta remota" +#: builtin/fetch.c msgid "unknown branch type" msgstr "tipus de branca desconegut" +#: builtin/fetch.c msgid "" "no source branch found;\n" "you need to specify exactly one branch with the --set-upstream option" @@ -5976,18 +7667,22 @@ msgstr "" "no s'ha trobat cap branca d'origen.\n" "heu d'especificar exactament una branca amb l'opció --set-upstream" +#: builtin/fetch.c #, c-format msgid "Fetching %s\n" msgstr "S'està obtenint %s\n" +#: builtin/fetch.c #, c-format msgid "could not fetch %s" msgstr "no s'ha pogut obtenir %s" +#: builtin/fetch.c #, c-format msgid "could not fetch '%s' (exit code: %d)\n" msgstr "no s'ha pogut obtenir «%s» (codi de sortida: %d)\n" +#: builtin/fetch.c msgid "" "no remote repository specified; please specify either a URL or a\n" "remote name from which new revisions should be fetched" @@ -5995,82 +7690,107 @@ msgstr "" "no s'ha especificat cap repositori remot. Especifiqueu un URL o\n" "un nom remot del qual s'han d'obtenir les revisions noves" +#: builtin/fetch.c msgid "you need to specify a tag name" msgstr "necessiteu especificar un nom d'etiqueta" +#: builtin/fetch.c builtin/pull.c msgid "fetch from all remotes" msgstr "obtén de tots els remots" +#: builtin/fetch.c builtin/pull.c msgid "set upstream for git pull/fetch" msgstr "estableix la font per a git pull/fetch" +#: builtin/fetch.c builtin/pull.c msgid "append to .git/FETCH_HEAD instead of overwriting" msgstr "annexa a .git/FETCH_HEAD en lloc de sobreescriure'l" +#: builtin/fetch.c msgid "use atomic transaction to update references" msgstr "usa una transacció atòmica per a actualitzar les referències" +#: builtin/fetch.c builtin/pull.c msgid "path to upload pack on remote end" msgstr "camà al qual pujar el paquet al costat remot" +#: builtin/fetch.c msgid "force overwrite of local reference" msgstr "força la sobreescriptura de la referència local" +#: builtin/fetch.c msgid "fetch from multiple remotes" msgstr "obtén de múltiples remots" +#: builtin/fetch.c builtin/pull.c msgid "fetch all tags and associated objects" msgstr "obtén totes les etiquetes i tots els objectes associats" +#: builtin/fetch.c msgid "do not fetch all tags (--no-tags)" msgstr "no obtinguis les etiquetes (--no-tags)" +#: builtin/fetch.c msgid "number of submodules fetched in parallel" msgstr "nombre de submòduls obtinguts en paral·lel" +#: builtin/fetch.c msgid "modify the refspec to place all refs within refs/prefetch/" msgstr "" "modifica l'especificació de referència per a col·locar totes les referències " "dins de refs/prefetch/" +#: builtin/fetch.c builtin/pull.c msgid "prune remote-tracking branches no longer on remote" msgstr "poda les branques amb seguiment remot que ja no estiguin en el remot" +#: builtin/fetch.c msgid "prune local tags no longer on remote and clobber changed tags" msgstr "" "poda les etiquetes locals que ja no existeixen al remot i adjunta les " "etiquetes que han canviat" +#: builtin/fetch.c builtin/pull.c msgid "on-demand" msgstr "sota demanda" +#: builtin/fetch.c msgid "control recursive fetching of submodules" msgstr "controla l'obtenció recursiva de submòduls" +#: builtin/fetch.c msgid "write fetched references to the FETCH_HEAD file" msgstr "escriu les referències obtingudes al fitxer FETCH_HEAD" +#: builtin/fetch.c builtin/pull.c msgid "keep downloaded pack" msgstr "retén el paquet baixat" +#: builtin/fetch.c msgid "allow updating of HEAD ref" msgstr "permet l'actualització de la referència HEAD" +#: builtin/fetch.c builtin/pull.c msgid "deepen history of shallow clone" msgstr "aprofundeix la història d'un clon superficial" +#: builtin/fetch.c builtin/pull.c msgid "deepen history of shallow repository based on time" msgstr "aprofundeix la història d'un clon superficial basat en una data" +#: builtin/fetch.c builtin/pull.c msgid "convert to a complete repository" msgstr "converteix en un repositori complet" +#: builtin/fetch.c msgid "re-fetch without negotiating common commits" msgstr "tornar a obtenir sense negociar comissions comunes" +#: builtin/fetch.c msgid "prepend this to submodule path output" msgstr "anteposa això a la sortida de camà del submòdul" +#: builtin/fetch.c msgid "" "default for recursive fetching of submodules (lower priority than config " "files)" @@ -6078,68 +7798,88 @@ msgstr "" "per defecte per a l'obtenció recursiva de submòduls (prioritat més baixa que " "els fitxers de configuració)" +#: builtin/fetch.c builtin/pull.c msgid "accept refs that update .git/shallow" msgstr "accepta les referències que actualitzin .git/shallow" +#: builtin/fetch.c builtin/pull.c msgid "refmap" msgstr "mapa de referències" +#: builtin/fetch.c builtin/pull.c msgid "specify fetch refmap" msgstr "especÃfica l'obtenció del mapa de referències" +#: builtin/fetch.c builtin/pull.c msgid "report that we have only objects reachable from this object" msgstr "informa que només hi ha objectes abastables des d'aquest objecte" +#: builtin/fetch.c msgid "do not fetch a packfile; instead, print ancestors of negotiation tips" msgstr "" "no obtinguis un fitxer de paquet; en canvi, mostra els avantpassats dels " "consells de negociació" +#: builtin/fetch.c msgid "run 'maintenance --auto' after fetching" msgstr "executa «maintenance --auto» després d'obtenir" +#: builtin/fetch.c builtin/pull.c msgid "check for forced-updates on all updated branches" msgstr "" "comprova si hi ha actualitzacions forçades a totes les branques actualitzades" +#: builtin/fetch.c msgid "write the commit-graph after fetching" msgstr "escriu el graf de comissions després de recollir" +#: builtin/fetch.c msgid "accept refspecs from stdin" msgstr "llegeix les especificacions de referència des de stdin" +#: builtin/fetch.c msgid "--negotiate-only needs one or more --negotiation-tip=*" msgstr "--negotiate-only necessita un o més --negotiation-tip=*" +#: builtin/fetch.c msgid "negative depth in --deepen is not supported" msgstr "no s'admet una profunditat negativa en --deepen" +#: builtin/fetch.c msgid "--unshallow on a complete repository does not make sense" msgstr "--unshallow en un repositori complet no té sentit" +#: builtin/fetch.c #, c-format msgid "failed to fetch bundles from '%s'" msgstr "no s'han pogut obtenir els paquets de «%s»" +#: builtin/fetch.c msgid "fetch --all does not take a repository argument" msgstr "fetch --all no accepta un argument de repositori" +#: builtin/fetch.c msgid "fetch --all does not make sense with refspecs" msgstr "fetch --all no té sentit amb especificacions de referència" +#: builtin/fetch.c #, c-format msgid "no such remote or remote group: %s" msgstr "no existeix un remot ni un grup remot: %s" +#: builtin/fetch.c msgid "fetching a group and specifying refspecs does not make sense" msgstr "obtenir un grup i especificar referències no té sentit" +#: builtin/fetch.c msgid "must supply remote when using --negotiate-only" msgstr "s'ha de subministrar el remot en usar --negotiate-only" +#: builtin/fetch.c msgid "protocol does not support --negotiate-only, exiting" msgstr "el protocol no admet --negotiate-only, se surt" +#: builtin/fetch.c msgid "" "--filter can only be used with the remote configured in extensions." "partialclone" @@ -6147,125 +7887,170 @@ msgstr "" "--filter només es pot utilitzar amb el remot configurat en extensions." "partialclone" +#: builtin/fetch.c msgid "--atomic can only be used when fetching from one remote" msgstr "l'opció --atomic només es pot usar quan s'obté des d'un remot" +#: builtin/fetch.c msgid "--stdin can only be used when fetching from one remote" msgstr "l'opció --stdin només es pot usar quan s'obté des d'un remot" +#: builtin/fmt-merge-msg.c msgid "" "git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]" msgstr "" "git fmt-merge-msg [-m <missatge>] [--log[=<n>] | --no-log] [--file <fitxer>]" +#: builtin/fmt-merge-msg.c msgid "populate log with at most <n> entries from shortlog" msgstr "emplena el registre amb <n> entrades del registre curt com a mà xim" +#: builtin/fmt-merge-msg.c msgid "alias for --log (deprecated)" msgstr "à lies per a --log (en desús)" +#: builtin/fmt-merge-msg.c msgid "text" msgstr "text" +#: builtin/fmt-merge-msg.c msgid "use <text> as start of message" msgstr "usa <text> com a inici de missatge" +#: builtin/fmt-merge-msg.c msgid "use <name> instead of the real target branch" msgstr "usa <nom> en lloc de la branca de destà real" +#: builtin/fmt-merge-msg.c msgid "file to read from" msgstr "fitxer del qual llegir" +#: builtin/for-each-ref.c msgid "git for-each-ref [<options>] [<pattern>]" msgstr "git for-each-ref [<opcions>] [<patró>]" +#: builtin/for-each-ref.c msgid "git for-each-ref [--points-at <object>]" msgstr "git for-each-ref [--points-at <objecte>]" +#: builtin/for-each-ref.c msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]" msgstr "git for-each-ref [--merged [<comissió>]] [--no-merged [<comissió>]]" +#: builtin/for-each-ref.c msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]" msgstr "" "git for-each-ref [--contains [<comissió>]] [--no-contains [<comissió>]]" +#: builtin/for-each-ref.c msgid "quote placeholders suitably for shells" msgstr "" "posa els marcadors de posició entre cometes adequades per a intèrprets " "d'ordres" +#: builtin/for-each-ref.c msgid "quote placeholders suitably for perl" msgstr "posa els marcadors de posició entre cometes adequades per al perl" +#: builtin/for-each-ref.c msgid "quote placeholders suitably for python" msgstr "posa els marcadors de posició entre cometes adequades per al python" +#: builtin/for-each-ref.c msgid "quote placeholders suitably for Tcl" msgstr "posa els marcadors de posició entre cometes adequades per al Tcl" +#: builtin/for-each-ref.c msgid "show only <n> matched refs" msgstr "mostra només <n> referències coincidents" +#: builtin/for-each-ref.c builtin/tag.c msgid "respect format colors" msgstr "respecta els colors del format" +#: builtin/for-each-ref.c msgid "print only refs which points at the given object" msgstr "imprimeix només les referències que assenyalin l'objecte donat" +#: builtin/for-each-ref.c msgid "print only refs that are merged" msgstr "imprimeix només les referències que s'han fusionat" +#: builtin/for-each-ref.c msgid "print only refs that are not merged" msgstr "imprimeix només les referències que no s'han fusionat" +#: builtin/for-each-ref.c msgid "print only refs which contain the commit" msgstr "imprimeix només les referències que continguin la comissió" +#: builtin/for-each-ref.c msgid "print only refs which don't contain the commit" msgstr "imprimeix només les referències que no continguin la comissió" +#: builtin/for-each-ref.c msgid "read reference patterns from stdin" msgstr "llegeix els patrons de referència de l'entrada està ndard" +#: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "inclou també la referència HEAD i les pseudoreferències" + +#: builtin/for-each-ref.c msgid "unknown arguments supplied with --stdin" msgstr "s'han proporcionat arguments desconeguts amb --stdin" +#: builtin/for-each-repo.c msgid "git for-each-repo --config=<config> [--] <arguments>" msgstr "git for-each-repo --config=<config> [--] <arguments>" +#: builtin/for-each-repo.c msgid "config" msgstr "config" +#: builtin/for-each-repo.c msgid "config key storing a list of repository paths" msgstr "clau de configuració emmagatzemant una llista de camins de repositori" +#: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "continua fins i tot si l'ordre falla en un repositori" + +#: builtin/for-each-repo.c msgid "missing --config=<config>" msgstr "falta --config=<config>" +#: builtin/for-each-repo.c #, c-format msgid "got bad config --config=%s" msgstr "s'ha obtingut una configuració incorrecta --config=%s" +#: builtin/fsck.c msgid "unknown" msgstr "desconegut" #. TRANSLATORS: e.g. error in tree 01bfda: <more explanation> +#: builtin/fsck.c #, c-format msgid "error in %s %s: %s" msgstr "error en %s %s: %s" #. TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> +#: builtin/fsck.c #, c-format msgid "warning in %s %s: %s" msgstr "avÃs en %s %s: %s" +#: builtin/fsck.c #, c-format msgid "broken link from %7s %s" msgstr "enllaç trencat de %7s %s" +#: builtin/fsck.c msgid "wrong object type in link" msgstr "tipus d'objecte incorrecte en l'enllaç" +#: builtin/fsck.c #, c-format msgid "" "broken link from %7s %s\n" @@ -6274,147 +8059,186 @@ msgstr "" "enllaç trencat des de %7s %s\n" " fins a %7s %s" +#: builtin/fsck.c builtin/prune.c connected.c msgid "Checking connectivity" msgstr "S'està comprovant la connectivitat" +#: builtin/fsck.c #, c-format msgid "missing %s %s" msgstr "%s %s manca" +#: builtin/fsck.c #, c-format msgid "unreachable %s %s" msgstr "%s %s inabastable" +#: builtin/fsck.c #, c-format msgid "dangling %s %s" msgstr "%s %s sense assignació" +#: builtin/fsck.c msgid "could not create lost-found" msgstr "no s'ha pogut crear el trobat-perdut" +#: builtin/fsck.c builtin/gc.c builtin/rebase.c rebase-interactive.c rerere.c +#: sequencer.c #, c-format msgid "could not write '%s'" msgstr "no s'ha pogut escriure «%s»" +#: builtin/fsck.c #, c-format msgid "could not finish '%s'" msgstr "no s'ha pogut finalitzar «%s»" +#: builtin/fsck.c #, c-format msgid "Checking %s" msgstr "S'està comprovant %s" +#: builtin/fsck.c #, c-format msgid "Checking connectivity (%d objects)" msgstr "S'està comprovant la connectivitat (%d objectes)" +#: builtin/fsck.c #, c-format msgid "Checking %s %s" msgstr "S'està comprovant %s %s" +#: builtin/fsck.c msgid "broken links" msgstr "enllaços trencats" +#: builtin/fsck.c #, c-format msgid "root %s" msgstr "arrel %s" +#: builtin/fsck.c #, c-format msgid "tagged %s %s (%s) in %s" msgstr "marcat %s %s (%s) a %s" +#: builtin/fsck.c #, c-format msgid "%s: object corrupt or missing" msgstr "%s: objecte corrupte o no trobat" +#: builtin/fsck.c #, c-format msgid "%s: invalid reflog entry %s" -msgstr "%s: entrada de referència no và lida %s" +msgstr "%s: entrada de registre de referències no và lida %s" +#: builtin/fsck.c #, c-format msgid "Checking reflog %s->%s" -msgstr "S'està comprovant reflog %s->%s" +msgstr "S'està comprovant el registre de referències %s->%s" +#: builtin/fsck.c #, c-format msgid "%s: invalid sha1 pointer %s" msgstr "%s: punter %s sha1 no và lid" +#: builtin/fsck.c #, c-format msgid "%s: not a commit" msgstr "%s: no és una comissió" +#: builtin/fsck.c msgid "notice: No default references" msgstr "avÃs: no hi ha referències per defecte" +#: builtin/fsck.c #, c-format msgid "%s: hash-path mismatch, found at: %s" msgstr "%s: el resum del camà no coincideix, trobat a: %s" +#: builtin/fsck.c #, c-format msgid "%s: object corrupt or missing: %s" msgstr "%s: objecte corrupte o no trobat: %s" +#: builtin/fsck.c #, c-format msgid "%s: object is of unknown type '%s': %s" msgstr "%s: l'objecte és de tipus desconegut «%s»: %s" +#: builtin/fsck.c #, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: no s'ha pogut analitzar l'objecte: %s" +#: builtin/fsck.c #, c-format msgid "bad sha1 file: %s" msgstr "fitxer sha1 malmès: %s" +#: builtin/fsck.c msgid "Checking object directory" msgstr "S'està comprovant el directori d'objecte" +#: builtin/fsck.c msgid "Checking object directories" msgstr "S'estan comprovant els directoris d'objecte" +#: builtin/fsck.c #, c-format msgid "Checking %s link" msgstr "S'està comprovant l'enllaç %s" +#: builtin/fsck.c builtin/index-pack.c #, c-format msgid "invalid %s" msgstr "%s no và lid" +#: builtin/fsck.c #, c-format msgid "%s points to something strange (%s)" msgstr "%s apunta a una cosa estranya (%s)" +#: builtin/fsck.c #, c-format msgid "%s: detached HEAD points at nothing" msgstr "%s: la HEAD separada no apunta a res" +#: builtin/fsck.c #, c-format msgid "notice: %s points to an unborn branch (%s)" msgstr "avÃs: %s apunta a una branca no nascuda (%s)" +#: builtin/fsck.c #, c-format msgid "Checking cache tree of %s" msgstr "S'està comprovant l'arbre de la memòria cau %s" +#: builtin/fsck.c #, c-format msgid "%s: invalid sha1 pointer in cache-tree of %s" msgstr "%s: punter sha1 no và lid a l'arbre de la memòria cau %s" +#: builtin/fsck.c msgid "non-tree in cache-tree" msgstr "un no arbre en l'arbre de la memòria cau" +#: builtin/fsck.c #, c-format msgid "%s: invalid sha1 pointer in resolve-undo of %s" msgstr "%s: punter sha1 no và lid a «resolve-undo» de %s" +#: builtin/fsck.c #, c-format msgid "unable to load rev-index for pack '%s'" msgstr "no s'ha pogut carregar l'Ãndex de reversió per al paquet «%s»" +#: builtin/fsck.c #, c-format msgid "invalid rev-index for pack '%s'" msgstr "rev-index no và lid per al paquet «%s»" +#: builtin/fsck.c msgid "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" @@ -6426,159 +8250,205 @@ msgstr "" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" " [--[no-]name-objects] [<objecte>...]" +#: builtin/fsck.c msgid "show unreachable objects" msgstr "mostra els objectes inabastables" +#: builtin/fsck.c msgid "show dangling objects" -msgstr "mostra els objectes penjants" +msgstr "mostra els objectes despenjats" +#: builtin/fsck.c msgid "report tags" msgstr "informa de les etiquetes" +#: builtin/fsck.c msgid "report root nodes" msgstr "informa dels nodes d'arrel" +#: builtin/fsck.c msgid "make index objects head nodes" -msgstr "fes dels objectes d'Ãndex nodes cap" +msgstr "fes dels objectes d'Ãndex nodes HEAD" +#: builtin/fsck.c msgid "make reflogs head nodes (default)" -msgstr "fes que els registres de referències siguin nodes cap (per defecte)" +msgstr "fes que els registres de referències siguin nodes HEAD (per defecte)" +#: builtin/fsck.c msgid "also consider packs and alternate objects" msgstr "també considera els paquets i els objectes alternatius" +#: builtin/fsck.c msgid "check only connectivity" msgstr "comprova només la connectivitat" +#: builtin/fsck.c builtin/mktag.c msgid "enable more strict checking" msgstr "habilita la comprovació més estricta" +#: builtin/fsck.c msgid "write dangling objects in .git/lost-found" -msgstr "escriu objectes penjants a .git/lost-found" +msgstr "escriu objectes despenjats a .git/lost-found" +#: builtin/fsck.c builtin/prune.c msgid "show progress" msgstr "mostra el progrés" +#: builtin/fsck.c msgid "show verbose names for reachable objects" msgstr "mostra els noms detallats dels objectes abastables" +#: builtin/fsck.c builtin/index-pack.c msgid "Checking objects" msgstr "S'estan comprovant els objectes" +#: builtin/fsck.c #, c-format msgid "%s: object missing" msgstr "%s: falta l'objecte" +#: builtin/fsck.c #, c-format msgid "invalid parameter: expected sha1, got '%s'" msgstr "parà metre no và lid: s'esperava sha1, s'ha obtingut «%s»" +#: builtin/fsmonitor--daemon.c msgid "git fsmonitor--daemon start [<options>]" msgstr "git fsmonitor--daemon start [<opcions>]" +#: builtin/fsmonitor--daemon.c msgid "git fsmonitor--daemon run [<options>]" msgstr "git fsmonitor--daemon run [<opcions>]" +#: builtin/fsmonitor--daemon.c #, c-format msgid "value of '%s' out of range: %d" msgstr "el valor de «%s» està fora de rang: %d" +#: builtin/fsmonitor--daemon.c #, c-format msgid "value of '%s' not bool or int: %d" msgstr "valor de «%s» no és booleà ni enter: %d" +#: builtin/fsmonitor--daemon.c #, c-format msgid "fsmonitor-daemon is watching '%s'\n" msgstr "fsmonitor-daemon està veient «%s»\n" +#: builtin/fsmonitor--daemon.c #, c-format msgid "fsmonitor-daemon is not watching '%s'\n" msgstr "fsmonitor-daemon no està vigilant «%s»\n" +#: builtin/fsmonitor--daemon.c #, c-format msgid "could not create fsmonitor cookie '%s'" msgstr "no s'ha pogut crear la galeta fsmonitor «%s»" +#: builtin/fsmonitor--daemon.c #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" msgstr "fsmonitor: cookie_result «%d» != SEEN" +#: builtin/fsmonitor--daemon.c #, c-format msgid "could not start IPC thread pool on '%s'" msgstr "no s'ha pogut iniciar el grup de fils IPC a «%s»" +#: builtin/fsmonitor--daemon.c msgid "could not start fsmonitor listener thread" msgstr "no s'ha pogut iniciar el fil receptor del fsmonitor" +#: builtin/fsmonitor--daemon.c msgid "could not start fsmonitor health thread" msgstr "no s'ha pogut iniciar el fil de salut del fsmonitor" +#: builtin/fsmonitor--daemon.c msgid "could not initialize listener thread" msgstr "no s'ha pogut inicialitzar el fil receptor" +#: builtin/fsmonitor--daemon.c msgid "could not initialize health thread" msgstr "no s'ha pogut inicialitzar el fil de salut" +#: builtin/fsmonitor--daemon.c #, c-format msgid "could not cd home '%s'" msgstr "no s'ha pogut fer cd home «%s»" +#: builtin/fsmonitor--daemon.c #, c-format msgid "fsmonitor--daemon is already running '%s'" msgstr "fsmonitor--daemon is already running «%s»" +#: builtin/fsmonitor--daemon.c #, c-format msgid "running fsmonitor-daemon in '%s'\n" msgstr "s'està executant fsmonitor-daemon en «%s»\n" +#: builtin/fsmonitor--daemon.c #, c-format msgid "starting fsmonitor-daemon in '%s'\n" msgstr "s'està iniciant fsmonitor-daemon a «%s»\n" +#: builtin/fsmonitor--daemon.c msgid "daemon failed to start" msgstr "el dimoni ha fallat en iniciar" +#: builtin/fsmonitor--daemon.c msgid "daemon not online yet" msgstr "el dimoni encara no està en lÃnia" +#: builtin/fsmonitor--daemon.c msgid "daemon terminated" msgstr "s'ha finalitzat el dimoni" +#: builtin/fsmonitor--daemon.c msgid "detach from console" msgstr "separat de la consola" +#: builtin/fsmonitor--daemon.c msgid "use <n> ipc worker threads" msgstr "usa <n> fils de treball ipc" +#: builtin/fsmonitor--daemon.c msgid "max seconds to wait for background daemon startup" msgstr "mà xim de segons a esperar a l'inici del dimoni en segon pla" +#: builtin/fsmonitor--daemon.c #, c-format msgid "invalid 'ipc-threads' value (%d)" msgstr "valor «ipc-threads» no và lid (%d)" +#: builtin/fsmonitor--daemon.c t/helper/test-cache-tree.c #, c-format msgid "Unhandled subcommand '%s'" msgstr "Subordre no gestionada «%s»" +#: builtin/fsmonitor--daemon.c msgid "fsmonitor--daemon not supported on this platform" msgstr "fsmonitor--daemon no és compatible amb aquesta plataforma" +#: builtin/gc.c msgid "git gc [<options>]" msgstr "git gc [<opcions>]" +#: builtin/gc.c #, c-format msgid "Failed to fstat %s: %s" msgstr "S'ha produït un error en fer fstat %s: %s" +#: builtin/gc.c #, c-format msgid "failed to parse '%s' value '%s'" msgstr "no s'ha pogut analitzar «%s» valor «%s»" +#: builtin/gc.c setup.c #, c-format msgid "cannot stat '%s'" msgstr "no es pot fer stat en «%s»" +#: builtin/gc.c #, c-format msgid "" "The last gc run reported the following. Please correct the root cause\n" @@ -6593,246 +8463,322 @@ msgstr "" "\n" "%s" +#: builtin/gc.c msgid "prune unreferenced objects" msgstr "poda objectes sense referència" +#: builtin/gc.c msgid "pack unreferenced objects separately" msgstr "empaqueta els objectes no referenciats de forma separada" +#: builtin/gc.c builtin/repack.c msgid "with --cruft, limit the size of new cruft packs" msgstr "amb --cruft, limiteu la mida dels paquets cruft nous" +#: builtin/gc.c msgid "be more thorough (increased runtime)" msgstr "sigues més exhaustiu (el temps d'execució augmenta)" +#: builtin/gc.c msgid "enable auto-gc mode" msgstr "habilita el mode de recollida d'escombraries automà tica" +#: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "fes la recollida de memòria brossa en segon pla" + +#: builtin/gc.c msgid "force running gc even if there may be another gc running" msgstr "" "força l'execució de gc encara que hi pugui haver un altre gc executant-se" +#: builtin/gc.c msgid "repack all other packs except the largest pack" msgstr "reempaqueta tots els altres paquets excepte el paquet més gran" +#: builtin/gc.c #, c-format msgid "failed to parse gc.logExpiry value %s" msgstr "no s'ha pogut analitzar el valor %s de gc.logExpiry" +#: builtin/gc.c #, c-format msgid "failed to parse prune expiry value %s" msgstr "no s'ha pogut analitzar el valor de venciment de la poda %s" +#: builtin/gc.c #, c-format msgid "Auto packing the repository in background for optimum performance.\n" msgstr "" "S'està empaquetant el repositori automà ticament en el rerefons per a un " "rendiment òptim.\n" +#: builtin/gc.c #, c-format msgid "Auto packing the repository for optimum performance.\n" msgstr "" "S'està empaquetant automà ticament el repositori per a un rendiment òptim.\n" +#: builtin/gc.c #, c-format msgid "See \"git help gc\" for manual housekeeping.\n" msgstr "Vegeu «git help gc» per a neteja manual.\n" +#: builtin/gc.c #, c-format msgid "" "gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)" msgstr "" "gc ja s'està executant en la mà quina «%s» pid %<PRIuMAX> (useu --force si no)" +#: builtin/gc.c msgid "" "There are too many unreachable loose objects; run 'git prune' to remove them." msgstr "" "Hi ha massa objectes solts inabastables; executeu «git prune» per a eliminar-" "los." +#: builtin/gc.c msgid "" "git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]" msgstr "" "git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]" +#: builtin/gc.c msgid "--no-schedule is not allowed" msgstr "--no-schedule no està permès" +#: builtin/gc.c #, c-format msgid "unrecognized --schedule argument '%s'" msgstr "argument --schedule no reconegut, «%s»" +#: builtin/gc.c msgid "failed to write commit-graph" msgstr "s'ha produït un error en escriure el graf de comissions" +#: builtin/gc.c msgid "failed to prefetch remotes" msgstr "s'ha produït un error en preobtenir els remots" +#: builtin/gc.c msgid "failed to start 'git pack-objects' process" msgstr "no s'ha pogut iniciar el procés «git pack-objects»" +#: builtin/gc.c msgid "failed to finish 'git pack-objects' process" msgstr "no s'ha pogut finalitzar el procés «git pack-objects»" +#: builtin/gc.c msgid "failed to write multi-pack-index" msgstr "no s'ha pogut escriure l'Ãndex del multipaquet" +#: builtin/gc.c msgid "'git multi-pack-index expire' failed" msgstr "ha fallat el venciment de «git multi-pack-index expire»" +#: builtin/gc.c msgid "'git multi-pack-index repack' failed" msgstr "ha fallat l'execució de «git multi-pack-index repack»" +#: builtin/gc.c msgid "" "skipping incremental-repack task because core.multiPackIndex is disabled" msgstr "" "s'està ometent la tasca incremental-repack perquè core.multiPackIndex està " "desactivat" +#: builtin/gc.c #, c-format msgid "lock file '%s' exists, skipping maintenance" msgstr "el fitxer de bloqueig «%s» existeix, s'omet el manteniment" +#: builtin/gc.c #, c-format msgid "task '%s' failed" msgstr "la tasca «%s» ha fallat" +#: builtin/gc.c #, c-format msgid "'%s' is not a valid task" msgstr "«%s» no és una tasca và lida" +#: builtin/gc.c #, c-format msgid "task '%s' cannot be selected multiple times" msgstr "la tasca «%s» no es pot seleccionar múltiples vegades" +#: builtin/gc.c msgid "run tasks based on the state of the repository" msgstr "executa les tasques basades en l'estat del repositori" +#: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "fes el manteniment en segon pla" + +#: builtin/gc.c msgid "frequency" msgstr "freqüència" +#: builtin/gc.c msgid "run tasks based on frequency" msgstr "executa les tasques basant-se en freqüència" +#: builtin/gc.c msgid "do not report progress or other information over stderr" -msgstr "no informeu sobre el progrés o altra informació as stderr" +msgstr "no informeu sobre el progrés o altra informació a stderr" +#: builtin/gc.c msgid "task" msgstr "tasca" +#: builtin/gc.c msgid "run a specific task" msgstr "executa una tasca especÃfica" +#: builtin/gc.c msgid "use at most one of --auto and --schedule=<frequency>" -msgstr "usa com a mà xim un entre --auto i --schedule=<frequency>" +msgstr "usa com a mà xim un entre --auto i --schedule=<freqüència>" +#: builtin/gc.c #, c-format msgid "unable to add '%s' value of '%s'" msgstr "no es pot afegir el valor «%s» de «%s»" +#: builtin/gc.c msgid "return success even if repository was not registered" msgstr "retorna èxit encara que el repositori no estigui registrat" +#: builtin/gc.c #, c-format msgid "unable to unset '%s' value of '%s'" msgstr "no es pot desassignar el valor «%s» de «%s»" +#: builtin/gc.c #, c-format msgid "repository '%s' is not registered" msgstr "el repositori «%s» no està registrat" +#: builtin/gc.c #, c-format msgid "failed to expand path '%s'" msgstr "s'ha produït un error en expandir el camà «%s»" +#: builtin/gc.c msgid "failed to start launchctl" msgstr "s'ha produït un error en iniciar launchctl" +#: builtin/gc.c #, c-format msgid "failed to create directories for '%s'" msgstr "s'ha produït un error en crear els directoris per a «%s»" +#: builtin/gc.c #, c-format msgid "failed to bootstrap service %s" msgstr "s'ha produït un error en arrencar el servei %s" +#: builtin/gc.c msgid "failed to create temp xml file" msgstr "no s'han pogut crear un fitxer xml temporal" +#: builtin/gc.c msgid "failed to start schtasks" msgstr "s'ha produït un error en iniciar schtasks" +#: builtin/gc.c msgid "failed to run 'crontab -l'; your system might not support 'cron'" msgstr "" "no s'ha pogut executar «crontab -l»; el vostre sistema podria no admetre " "«cron»" +#: builtin/gc.c msgid "failed to create crontab temporary file" msgstr "no s'ha pogut crear un fitxer temporal crontab" +#: builtin/gc.c msgid "failed to open temporary file" msgstr "no s'ha pogut obrir el fitxer temporal" +#: builtin/gc.c msgid "failed to run 'crontab'; your system might not support 'cron'" msgstr "" "no s'ha pogut executar «crontab»; el vostre sistema podria no admetre «cron»" +#: builtin/gc.c msgid "'crontab' died" msgstr "«crontab» ha mort" +#: builtin/gc.c builtin/worktree.c #, c-format msgid "failed to delete '%s'" msgstr "s'ha produït un error en suprimir «%s»" +#: builtin/gc.c rerere.c #, c-format msgid "failed to flush '%s'" msgstr "no s'ha pogut buidar «%s»" +#: builtin/gc.c msgid "failed to start systemctl" msgstr "s'ha produït un error en iniciar systemctl" +#: builtin/gc.c msgid "failed to run systemctl" msgstr "s'ha produït un error en executar systemctl" +#: builtin/gc.c #, c-format msgid "unrecognized --scheduler argument '%s'" msgstr "l'argument --scheduler no reconegut «%s»" +#: builtin/gc.c msgid "neither systemd timers nor crontab are available" msgstr "ni els temporitzadors de systemd ni de crontab estan disponibles" +#: builtin/gc.c #, c-format msgid "%s scheduler is not available" msgstr "el planificador %s no està disponible" +#: builtin/gc.c msgid "another process is scheduling background maintenance" msgstr "un altre procés està planificant un manteniment en segon pla" +#: builtin/gc.c msgid "git maintenance start [--scheduler=<scheduler>]" msgstr "git maintenance start [--scheduler=<scheduler>]" +#: builtin/gc.c msgid "scheduler" msgstr "planificador" +#: builtin/gc.c msgid "scheduler to trigger git maintenance run" msgstr "planificador per a activar l'execució de manteniment del git" +#: builtin/gc.c msgid "failed to set up maintenance schedule" msgstr "no s'ha pogut configurar la planificació del manteniment" +#: builtin/gc.c msgid "failed to add repo to global config" msgstr "no s'ha pogut afegir un repositori a la configuració global" +#: builtin/gc.c msgid "git maintenance <subcommand> [<options>]" -msgstr "git maintenance <subcommand> [<opcions>]" +msgstr "git maintenance <subordre> [<opcions>]" +#: builtin/grep.c msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" msgstr "git grep [<opcions>] [-e] <patró> [<revisió>...] [[--] <camÃ>...]" +#: builtin/grep.c #, c-format msgid "grep: failed to create thread: %s" msgstr "grep: s'ha produït un error en crear fil: %s" +#: builtin/grep.c #, c-format msgid "invalid number of threads specified (%d) for %s" msgstr "s'ha especificat un nombre de fils no và lid (%d) per a %s" @@ -6842,203 +8788,261 @@ msgstr "s'ha especificat un nombre de fils no và lid (%d) per a %s" #. variable for tweaking threads, currently #. grep.threads #. +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c #, c-format msgid "no threads support, ignoring %s" msgstr "no s'admeten fils, s'ignorarà %s" -#, c-format -msgid "unable to read tree (%s)" -msgstr "no s'ha pogut llegir l'arbre (%s)" - +#: builtin/grep.c #, c-format msgid "unable to read tree %s" msgstr "no s'ha pogut llegir l'arbre %s" +#: builtin/grep.c #, c-format msgid "unable to grep from object of type %s" msgstr "no es pot fer grep des d'un objecte de tipus %s" +#: builtin/grep.c #, c-format msgid "switch `%c' expects a numerical value" msgstr "l'opció «%c» espera un valor numèric" +#: builtin/grep.c msgid "search in index instead of in the work tree" msgstr "cerca en l'Ãndex en lloc de l'arbre de treball" +#: builtin/grep.c msgid "find in contents not managed by git" msgstr "cerca en continguts no gestionats per git" +#: builtin/grep.c msgid "search in both tracked and untracked files" msgstr "cerca tant en fitxers seguits com en no seguits" +#: builtin/grep.c msgid "ignore files specified via '.gitignore'" msgstr "ignora els fitxers especificats mitjançant «.gitignore»" +#: builtin/grep.c msgid "recursively search in each submodule" msgstr "cerca recursivament a cada submòdul" +#: builtin/grep.c msgid "show non-matching lines" msgstr "mostra les lÃnies no coincidents" +#: builtin/grep.c msgid "case insensitive matching" msgstr "coincidència no distingeix entre majúscules i minúscules" +#: builtin/grep.c msgid "match patterns only at word boundaries" msgstr "coincideix amb els patrons només als lÃmits de paraula" +#: builtin/grep.c msgid "process binary files as text" msgstr "processa els fitxers binaris com a text" +#: builtin/grep.c msgid "don't match patterns in binary files" msgstr "no cerquis els patrons en els fitxers binaris" +#: builtin/grep.c msgid "process binary files with textconv filters" msgstr "processa els fitxers binaris amb filtres de textconv" +#: builtin/grep.c msgid "search in subdirectories (default)" msgstr "cerca als subdirectoris (per defecte)" +#: builtin/grep.c msgid "descend at most <n> levels" msgstr "descendeix com a mà xim <n> nivells" +#: builtin/grep.c msgid "use extended POSIX regular expressions" msgstr "usa les expressions regulars POSIX ampliades" +#: builtin/grep.c msgid "use basic POSIX regular expressions (default)" msgstr "usa les expressions regulars POSIX bà siques (per defecte)" +#: builtin/grep.c msgid "interpret patterns as fixed strings" msgstr "interpreta els patrons com a cadenes fixes" +#: builtin/grep.c msgid "use Perl-compatible regular expressions" msgstr "usa les expressions regulars compatibles amb Perl" +#: builtin/grep.c msgid "show line numbers" msgstr "mostra els números de lÃnia" +#: builtin/grep.c msgid "show column number of first match" msgstr "mostra el nombre de columna de la primera coincidència" +#: builtin/grep.c msgid "don't show filenames" msgstr "no mostris els noms de fitxer" +#: builtin/grep.c msgid "show filenames" msgstr "mostra els noms de fitxer" +#: builtin/grep.c msgid "show filenames relative to top directory" msgstr "mostra els noms de fitxer relatius al directori superior" +#: builtin/grep.c msgid "show only filenames instead of matching lines" msgstr "mostra només els noms de fitxer en lloc de les lÃnies coincidents" +#: builtin/grep.c msgid "synonym for --files-with-matches" msgstr "sinònim de --files-with-matches" +#: builtin/grep.c msgid "show only the names of files without match" msgstr "mostra només els noms dels fitxers sense coincidència" +#: builtin/grep.c msgid "print NUL after filenames" msgstr "imprimeix NUL després dels noms de fitxer" +#: builtin/grep.c msgid "show only matching parts of a line" msgstr "mostra només les parts de coincidents de la lÃnia" +#: builtin/grep.c msgid "show the number of matches instead of matching lines" msgstr "mostra el nombre de coincidències en lloc de les lÃnies coincidents" +#: builtin/grep.c msgid "highlight matches" msgstr "ressalta les coincidències" +#: builtin/grep.c msgid "print empty line between matches from different files" msgstr "imprimeix una lÃnia buida entre coincidències de fitxers distints" +#: builtin/grep.c msgid "show filename only once above matches from same file" msgstr "" "mostra el nom de fitxer només una vegada a dalt de les coincidències del " "mateix fitxer" +#: builtin/grep.c msgid "show <n> context lines before and after matches" msgstr "mostra <n> lÃnies de context abans i després d'una coincidència" +#: builtin/grep.c msgid "show <n> context lines before matches" msgstr "mostra <n> lÃnies de context abans d'una coincidència" +#: builtin/grep.c msgid "show <n> context lines after matches" msgstr "mostra <n> lÃnies de context després d'una coincidència" +#: builtin/grep.c msgid "use <n> worker threads" msgstr "usa <n> fils de treball" +#: builtin/grep.c msgid "shortcut for -C NUM" msgstr "drecera per a -C NUM" +#: builtin/grep.c msgid "show a line with the function name before matches" msgstr "mostra una lÃnia amb el nom de funció abans de les coincidències" +#: builtin/grep.c msgid "show the surrounding function" msgstr "mostra la funció circumdant" +#: builtin/grep.c msgid "read patterns from file" msgstr "llegeix els patrons des d'un fitxer" +#: builtin/grep.c msgid "match <pattern>" msgstr "coincideix amb <patró>" +#: builtin/grep.c msgid "combine patterns specified with -e" msgstr "combina els patrons especificats amb -e" +#: builtin/grep.c msgid "indicate hit with exit status without output" msgstr "indica coincidència amb estat de sortida sense sortida textual" +#: builtin/grep.c msgid "show only matches from files that match all patterns" msgstr "" "mostra només les coincidències dels fitxers que coincideixin amb tots els " "patrons" +#: builtin/grep.c msgid "pager" msgstr "paginador" +#: builtin/grep.c msgid "show matching files in the pager" msgstr "mostra els fitxers coincidents en el paginador" +#: builtin/grep.c msgid "allow calling of grep(1) (ignored by this build)" msgstr "permet la invocació de grep(1) (ignorat per aquesta compilació)" +#: builtin/grep.c msgid "maximum number of results per file" msgstr "nombre mà xim de resultats per fitxer" +#: builtin/grep.c msgid "no pattern given" msgstr "no s'ha donat cap patró" +#: builtin/grep.c msgid "--no-index or --untracked cannot be used with revs" msgstr "--no-index o --untracked no es pot usar amb revisions" +#: builtin/grep.c #, c-format msgid "unable to resolve revision: %s" msgstr "no s'ha pogut resoldre la revisió: %s" +#: builtin/grep.c msgid "--untracked not supported with --recurse-submodules" msgstr "--untracked no s'admet amb --recurse-submodules" +#: builtin/grep.c msgid "invalid option combination, ignoring --threads" msgstr "combinació d'opcions no và lida, s'està ignorant --threads" +#: builtin/grep.c builtin/pack-objects.c msgid "no threads support, ignoring --threads" msgstr "no s'admeten fils, s'ignorarà --threads" +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c #, c-format msgid "invalid number of threads specified (%d)" msgstr "s'ha especificat un nombre de fils no và lid (%d)" +#: builtin/grep.c msgid "--open-files-in-pager only works on the worktree" msgstr "--open-files-in-pager només funciona en l'arbre de treball" +#: builtin/grep.c msgid "--[no-]exclude-standard cannot be used for tracked contents" msgstr "--[no-]exclude-standard no es pot utilitzar per als continguts seguits" +#: builtin/grep.c msgid "both --cached and trees are given" msgstr "ambdós --cached i arbres venen donats" +#: builtin/hash-object.c msgid "" "git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" " [--stdin [--literally]] [--] <file>..." @@ -7046,91 +9050,117 @@ msgstr "" "git hash-object [-t <tipus>] [-w] [--path=<fitxer> | --no-filters]\n" " [--stdin [--literally]] [--] <fitxer>..." +#: builtin/hash-object.c msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]" msgstr "git hash-object [-t <tipus>] [-w] --stdin-paths [--no-filters]" +#: builtin/hash-object.c msgid "object type" msgstr "tipus d'objecte" +#: builtin/hash-object.c msgid "write the object into the object database" msgstr "escriu l'objecte a la base de dades d'objectes" +#: builtin/hash-object.c msgid "read the object from stdin" msgstr "llegeix l'objecte des de stdin" +#: builtin/hash-object.c msgid "store file as is without filters" msgstr "emmagatzema el fitxer tal com és sense filtres" +#: builtin/hash-object.c msgid "" "just hash any random garbage to create corrupt objects for debugging Git" msgstr "" "només suma qualsevol brossa aleatòria per a crear objectes malmesos per a " "depurar al Git" +#: builtin/hash-object.c msgid "process file as it were from this path" msgstr "processa el fitxer com si fos d'aquest camÃ" +#: builtin/help.c msgid "print all available commands" msgstr "imprimeix totes les ordres disponibles" +#: builtin/help.c msgid "show external commands in --all" msgstr "mostra les ordres externes a --all" +#: builtin/help.c msgid "show aliases in --all" msgstr "mostra els à lies a --all" +#: builtin/help.c msgid "exclude guides" msgstr "exclou guies" +#: builtin/help.c msgid "show man page" msgstr "mostra la pà gina de manual" +#: builtin/help.c msgid "show manual in web browser" msgstr "mostra la pà gina de manual en el navegador web" +#: builtin/help.c msgid "show info page" msgstr "mostra la pà gina d'informació" +#: builtin/help.c msgid "print command description" msgstr "imprimeix la descripció de l'ordre" +#: builtin/help.c msgid "print list of useful guides" msgstr "imprimeix la llista de guies útils" +#: builtin/help.c msgid "print list of user-facing repository, command and file interfaces" msgstr "" "imprimeix la llista de repositoris, ordres i interfÃcies de fitxers que veu " "l'usuari" +#: builtin/help.c msgid "print list of file formats, protocols and other developer interfaces" msgstr "" "mostra la llista de formats de fitxer, protocols i altres interfÃcies de " "desenvolupador" +#: builtin/help.c msgid "print all configuration variable names" msgstr "imprimeix tots els noms de les variables de configuració" +#: builtin/help.c msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]" -msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]" +msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<ordre>|<doc>]" +#: builtin/help.c #, c-format msgid "unrecognized help format '%s'" msgstr "format d'ajuda no reconegut «%s»" +#: builtin/help.c msgid "Failed to start emacsclient." msgstr "S'ha produït un error en iniciar emacsclient." +#: builtin/help.c msgid "Failed to parse emacsclient version." msgstr "S'ha produït un error en analitzar la versió d'emacsclient." +#: builtin/help.c #, c-format msgid "emacsclient version '%d' too old (< 22)." msgstr "la versió d'emacsclient «%d» és massa vella (< 22)." +#: builtin/help.c #, c-format msgid "failed to exec '%s'" msgstr "s'ha produït un error en executar «%s»" +#: builtin/help.c #, c-format msgid "" "'%s': path for unsupported man viewer.\n" @@ -7139,6 +9169,7 @@ msgstr "" "«%s»: camà a un visualitzador de manuals no compatible.\n" "Considereu usar «man.<eina>.cmd» en lloc d'això." +#: builtin/help.c #, c-format msgid "" "'%s': cmd for supported man viewer.\n" @@ -7147,41 +9178,51 @@ msgstr "" "«%s»: ordre per a un visualitzador de manuals compatible.\n" "Considereu usar «man.<eina>.path» en lloc d'això." +#: builtin/help.c #, c-format msgid "'%s': unknown man viewer." msgstr "«%s»: visualitzador de manuals desconegut." +#: builtin/help.c msgid "no man viewer handled the request" msgstr "cap visualitzador de manuals ha gestionat la sol·licitud" +#: builtin/help.c msgid "no info viewer handled the request" msgstr "cap visualitzador d'informació ha gestionat la sol·licitud" +#: builtin/help.c git.c #, c-format msgid "'%s' is aliased to '%s'" msgstr "«%s» és un à lies de «%s»" +#: builtin/help.c git.c #, c-format msgid "bad alias.%s string: %s" msgstr "cadena «alias.%s» incorrecte: %s" +#: builtin/help.c #, c-format msgid "the '%s' option doesn't take any non-option arguments" msgstr "l'opció «%s» no pren cap argument que no sigui una opció" +#: builtin/help.c msgid "" "the '--no-[external-commands|aliases]' options can only be used with '--all'" msgstr "" "les opcions «--no-[external-commands|aliases]» només es poden utilitzar amb " "«--all»" +#: builtin/help.c #, c-format msgid "usage: %s%s" msgstr "ús: %s%s" +#: builtin/help.c msgid "'git help config' for more information" msgstr "«git help config» per a més informació" +#: builtin/hook.c msgid "" "git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-" "args>]" @@ -7189,75 +9230,95 @@ msgstr "" "git hook run [--ignore-missing] [--to-stdin=<camÃ>] <hook-name> [-- <hook-" "args>]" +#: builtin/hook.c msgid "silently ignore missing requested <hook-name>" msgstr "ignora silenciosament la sol·licitud <hook-name> perduda" +#: builtin/hook.c msgid "file to read into hooks' stdin" msgstr "fitxer per a llegir a l'entrada està ndard dels lligams" +#: builtin/index-pack.c #, c-format msgid "object type mismatch at %s" msgstr "hi ha una discordança de tipus d'objecte a %s" +#: builtin/index-pack.c #, c-format msgid "did not receive expected object %s" msgstr "no s'ha rebut l'objecte esperat %s" +#: builtin/index-pack.c #, c-format msgid "object %s: expected type %s, found %s" msgstr "objecte %s: s'esperava el tipus %s, s'ha trobat %s" +#: builtin/index-pack.c #, c-format msgid "cannot fill %d byte" msgid_plural "cannot fill %d bytes" msgstr[0] "no es pot omplir %d octet" msgstr[1] "no es poden omplir %d octets" +#: builtin/index-pack.c msgid "early EOF" msgstr "EOF prematur" +#: builtin/index-pack.c msgid "read error on input" msgstr "error de lectura d'entrada" +#: builtin/index-pack.c msgid "used more bytes than were available" msgstr "s'han usat més octets que hi havia disponibles" +#: builtin/index-pack.c builtin/pack-objects.c msgid "pack too large for current definition of off_t" msgstr "paquet massa gran per a la definició actual d'off_t" +#: builtin/index-pack.c #, c-format msgid "pack exceeds maximum allowed size (%s)" msgstr "el paquet supera la mida mà xima permesa (%s)" +#: builtin/index-pack.c msgid "pack signature mismatch" msgstr "hi ha una discordança de signatura de paquet" +#: builtin/index-pack.c #, c-format msgid "pack version %<PRIu32> unsupported" msgstr "la versió de paquet %<PRIu32> no és compatible" +#: builtin/index-pack.c #, c-format msgid "pack has bad object at offset %<PRIuMAX>: %s" msgstr "el paquet té un objecte incorrecte a la posició %<PRIuMAX>: %s" +#: builtin/index-pack.c #, c-format msgid "inflate returned %d" msgstr "la inflació ha retornat %d" +#: builtin/index-pack.c msgid "offset value overflow for delta base object" msgstr "" "desbordament de valor de desplaçament per a l'objecte base de diferències" +#: builtin/index-pack.c msgid "delta base offset is out of bound" msgstr "el desplaçament de base de diferències està fora de lÃmits" +#: builtin/index-pack.c #, c-format msgid "unknown object type %d" msgstr "tipus d'objecte desconegut %d" +#: builtin/index-pack.c msgid "cannot pread pack file" msgstr "no es pot fer pread en el fitxer empaquetat" +#: builtin/index-pack.c #, c-format msgid "premature end of pack file, %<PRIuMAX> byte missing" msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing" @@ -7265,150 +9326,189 @@ msgstr[0] "el final del fitxer empaquetat és prematur, manca %<PRIuMAX> octet" msgstr[1] "" "el final del fitxer empaquetat és prematur, manquen %<PRIuMAX> octets" +#: builtin/index-pack.c msgid "serious inflate inconsistency" msgstr "hi ha una inconsistència seriosa d'inflació" +#: builtin/index-pack.c #, c-format msgid "SHA1 COLLISION FOUND WITH %s !" msgstr "S'HA TROBAT UNA COL·LISIÓ SHA1 AMB %s !" +#: builtin/index-pack.c #, c-format msgid "cannot read existing object info %s" msgstr "no es pot llegir la informació d'objecte existent %s" +#: builtin/index-pack.c #, c-format msgid "cannot read existing object %s" msgstr "no es pot llegir l'objecte existent %s" +#: builtin/index-pack.c #, c-format msgid "invalid blob object %s" msgstr "objecte de blob no và lid %s" +#: builtin/index-pack.c msgid "fsck error in packed object" msgstr "fsck error en un objecte empaquetat" +#: builtin/index-pack.c #, c-format msgid "Not all child objects of %s are reachable" msgstr "No tots els objectes fills de %s són abastables" +#: builtin/index-pack.c msgid "failed to apply delta" msgstr "s'ha produït un error en aplicar la diferència" +#: builtin/index-pack.c msgid "Receiving objects" msgstr "S'estan rebent objectes" +#: builtin/index-pack.c msgid "Indexing objects" msgstr "S'estan indexant objectes" +#: builtin/index-pack.c msgid "pack is corrupted (SHA1 mismatch)" msgstr "el paquet és malmès (discordança SHA1)" +#: builtin/index-pack.c msgid "cannot fstat packfile" msgstr "no es pot fer fstat en el fitxer de paquet" +#: builtin/index-pack.c msgid "pack has junk at the end" msgstr "el paquet té brossa al seu final" +#: builtin/index-pack.c msgid "confusion beyond insanity in parse_pack_objects()" msgstr "confusió més enllà de la bogeria en parse_pack_objects()" +#: builtin/index-pack.c msgid "Resolving deltas" msgstr "S'estan resolent les diferències" +#: builtin/index-pack.c builtin/pack-objects.c #, c-format msgid "unable to create thread: %s" msgstr "no s'ha pogut crear fil: %s" +#: builtin/index-pack.c msgid "confusion beyond insanity" msgstr "confusió més enllà de la bogeria" +#: builtin/index-pack.c #, c-format msgid "completed with %d local object" msgid_plural "completed with %d local objects" msgstr[0] "s'ha completat amb %d objecte local" msgstr[1] "s'ha completat amb %d objectes locals" +#: builtin/index-pack.c #, c-format msgid "Unexpected tail checksum for %s (disk corruption?)" msgstr "Suma de verificació final no esperada per a %s (corrupció de disc?)" +#: builtin/index-pack.c #, c-format msgid "pack has %d unresolved delta" msgid_plural "pack has %d unresolved deltas" msgstr[0] "el paquet té %d diferència no resolta" msgstr[1] "el paquet té %d diferències no resoltes" +#: builtin/index-pack.c #, c-format msgid "unable to deflate appended object (%d)" msgstr "no s'ha pogut desinflar l'objecte annexat (%d)" +#: builtin/index-pack.c #, c-format msgid "local object %s is corrupt" msgstr "l'objecte local %s és malmès" +#: builtin/index-pack.c #, c-format msgid "packfile name '%s' does not end with '.%s'" msgstr "el nom del fitxer de paquet «%s» no acaba amb «.%s»" +#: builtin/index-pack.c #, c-format msgid "cannot write %s file '%s'" msgstr "no es pot escriure «%s» al fitxer «%s»" +#: builtin/index-pack.c #, c-format msgid "cannot close written %s file '%s'" msgstr "no s'ha pogut tancar el fitxer %s escrit «%s»" +#: builtin/index-pack.c #, c-format msgid "unable to rename temporary '*.%s' file to '%s'" msgstr "no s'ha pogut canviar el nom del fitxer temporal «*.%s» a «%s»" +#: builtin/index-pack.c msgid "error while closing pack file" msgstr "error en tancar el fitxer empaquetat" +#: builtin/index-pack.c builtin/pack-objects.c #, c-format msgid "bad pack.indexVersion=%<PRIu32>" msgstr "bad pack.indexVersion=%<PRIu32>" +#: builtin/index-pack.c #, c-format msgid "Cannot open existing pack file '%s'" msgstr "No es pot obrir el fitxer empaquetat existent «%s»" +#: builtin/index-pack.c #, c-format msgid "Cannot open existing pack idx file for '%s'" msgstr "No es pot obrir el fitxer d'Ãndex de paquets existent de «%s»" +#: builtin/index-pack.c #, c-format msgid "non delta: %d object" msgid_plural "non delta: %d objects" msgstr[0] "sense diferències: %d objecte" msgstr[1] "sense diferències: %d objectes" +#: builtin/index-pack.c #, c-format msgid "chain length = %d: %lu object" msgid_plural "chain length = %d: %lu objects" msgstr[0] "longitud de cadena = %d: %lu objecte" msgstr[1] "longitud de cadena = %d: %lu objectes" +#: builtin/index-pack.c msgid "Cannot come back to cwd" msgstr "No es pot tornar al directori de treball actual" +#: builtin/index-pack.c #, c-format msgid "bad %s" msgstr "%s incorrecte" +#: builtin/index-pack.c builtin/init-db.c setup.c #, c-format msgid "unknown hash algorithm '%s'" msgstr "algorisme de resum desconegut «%s»" +#: builtin/index-pack.c msgid "--stdin requires a git repository" msgstr "--stdin requereix un repositori git" +#: builtin/index-pack.c msgid "--verify with no packfile name given" msgstr "s'ha donat --verify sense nom de fitxer de paquet" +#: builtin/index-pack.c builtin/unpack-objects.c msgid "fsck error in pack objects" msgstr "error fsck als objectes del paquet" +#: builtin/init-db.c msgid "" "git init [-q | --quiet] [--bare] [--template=<template-directory>]\n" " [--separate-git-dir <git-dir>] [--object-format=<format>]\n" @@ -7420,32 +9520,40 @@ msgstr "" " [--separate-git-dir <git-dir>] [--object-format=<format>]\n" " [--ref-format=<format>]\n" " [-b <branch-name> | --initial-branch=<branch-name>]\n" -" [--shared[=<permissions>]] [<directory>]" +" [--shared[=<permissions>]] [<directori>]" +#: builtin/init-db.c msgid "permissions" msgstr "permisos" +#: builtin/init-db.c msgid "specify that the git repository is to be shared amongst several users" msgstr "" "especifica que el repositori de git es compartirà entre diversos usuaris" +#: builtin/init-db.c msgid "override the name of the initial branch" msgstr "sobreescriu el nom de la branca inicial" +#: builtin/init-db.c builtin/verify-pack.c msgid "hash" msgstr "resum" +#: builtin/init-db.c builtin/show-index.c builtin/verify-pack.c msgid "specify the hash algorithm to use" msgstr "especifiqueu l'algorisme de resum a usar" +#: builtin/init-db.c #, c-format msgid "cannot mkdir %s" msgstr "no es pot mkdir %s" +#: builtin/init-db.c #, c-format msgid "cannot chdir to %s" msgstr "no es pot canviar de directori a %s" +#: builtin/init-db.c #, c-format msgid "" "%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-" @@ -7454,174 +9562,252 @@ msgstr "" "no es permet %s (o --work-tree=<directori>) sense especificar %s (o --git-" "dir=<directori>)" +#: builtin/init-db.c #, c-format msgid "Cannot access work tree '%s'" msgstr "No es pot accedir a l'arbre de treball «%s»" +#: builtin/init-db.c msgid "--separate-git-dir incompatible with bare repository" msgstr "--separate-git-dir és incompatible amb un repositori nu" +#: builtin/interpret-trailers.c msgid "" "git interpret-trailers [--in-place] [--trim-empty]\n" -" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n" +" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" " [--parse] [<file>...]" msgstr "" "git interpret-trailers [--in-place] [--trim-empty]\n" -" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n" -" [--parse] [<file>...]" +" [(--trailer (<clau>|<alies-clau>)[(=|:)<valor>])...]\n" +" [--parse] [<fitxer>...]" + +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "no s'ha pogut fer stat a %s" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "el fitxer %s no és un fitxer regular" +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "el fitxer %s no és gravable per l'usuari" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "no s'ha pogut obrir el fitxer temporal" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "no s'ha pogut llegir el fitxer d'entrada «%s»" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "no s'ha pogut llegir des de stdin" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "no s'ha pogut canviar el nom del fitxer temporal a %s" + +#: builtin/interpret-trailers.c msgid "edit files in place" msgstr "edita els fitxers in situ" +#: builtin/interpret-trailers.c msgid "trim empty trailers" msgstr "escurça els remolcs buits" +#: builtin/interpret-trailers.c msgid "placement" msgstr "posicionament" +#: builtin/interpret-trailers.c msgid "where to place the new trailer" msgstr "on ubicar el «trailer» nou" +#: builtin/interpret-trailers.c msgid "action if trailer already exists" msgstr "acció si el «trailer» ja existeix" +#: builtin/interpret-trailers.c msgid "action if trailer is missing" msgstr "acció si el «trailer» falta" +#: builtin/interpret-trailers.c msgid "output only the trailers" msgstr "mostra només els «trailer»" +#: builtin/interpret-trailers.c msgid "do not apply trailer.* configuration variables" msgstr "no apliquis les variables de configuració trailer.*" +#: builtin/interpret-trailers.c msgid "reformat multiline trailer values as single-line values" msgstr "" "reformata els valors del trà iler multilÃnia com a valors de lÃnia única" +#: builtin/interpret-trailers.c msgid "alias for --only-trailers --only-input --unfold" msgstr "à lies per a --only-trailers --only-input --unfold" +#: builtin/interpret-trailers.c msgid "do not treat \"---\" as the end of input" msgstr "no tractis «---» com el final de l'entrada" +#: builtin/interpret-trailers.c msgid "trailer(s) to add" msgstr "remolcs a afegir" +#: builtin/interpret-trailers.c msgid "--trailer with --only-input does not make sense" msgstr "--trailer amb --only-input no té sentit" +#: builtin/interpret-trailers.c msgid "no input file given for in-place editing" msgstr "no s'ha donat cap fitxer d'entrada per a edició in situ" +#: builtin/log.c msgid "git log [<options>] [<revision-range>] [[--] <path>...]" msgstr "git log [<opcions>] [<rang-de-revisions>] [[--] <camÃ>...]" +#: builtin/log.c msgid "git show [<options>] <object>..." msgstr "git show [<opcions>] <objecte>..." +#: builtin/log.c #, c-format msgid "invalid --decorate option: %s" msgstr "opció --decorate no và lida: %s" +#: builtin/log.c diff.c msgid "suppress diff output" msgstr "omet la sortida de diferències" +#: builtin/log.c msgid "show source" msgstr "mostra la font" +#: builtin/log.c msgid "clear all previously-defined decoration filters" msgstr "neteja tots els filtres de decoració prèviament definits" +#: builtin/log.c msgid "only decorate refs that match <pattern>" msgstr "només decora les referències que coincideixin amb <patró>" +#: builtin/log.c msgid "do not decorate refs that match <pattern>" msgstr "no decoris les referències que coincideixen amb <patró>" +#: builtin/log.c msgid "decorate options" msgstr "opcions de decoració" +#: builtin/log.c msgid "" "trace the evolution of line range <start>,<end> or function :<funcname> in " "<file>" msgstr "" -"traça l'evolució del rang de lÃnia <start>,<end> o funcions :<funcname> a " -"<fitxer>" +"traça l'evolució del rang de lÃnia <inici>,<final> o funcions :<nom-funció> " +"a <fitxer>" +#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c #, c-format msgid "unrecognized argument: %s" msgstr "argument no reconegut: %s" +#: builtin/log.c msgid "-L<range>:<file> cannot be used with pathspec" -msgstr "-L<range>:<fitxer> no es pot usar amb una especificació de camÃ" +msgstr "-L<rang>:<fitxer> no es pot usar amb una especificació de camÃ" +#: builtin/log.c #, c-format msgid "Final output: %d %s\n" msgstr "Sortida final: %d %s\n" -msgid "unable to create temporary object directory" -msgstr "no s'ha pogut crear el directori temporal de l'objecte" - +#: builtin/log.c #, c-format msgid "git show %s: bad file" msgstr "git show %s: fitxer incorrecte" +#: builtin/log.c #, c-format msgid "could not read object %s" msgstr "no s'ha pogut llegir l'objecte %s" +#: builtin/log.c #, c-format msgid "unknown type: %d" msgstr "tipus desconegut: %d" +#: builtin/log.c #, c-format msgid "%s: invalid cover from description mode" msgstr "%s: cobertura no và lida des del mode descripció" +#: builtin/log.c msgid "format.headers without value" msgstr "format.headers sense valor" +#: builtin/log.c #, c-format msgid "cannot open patch file %s" msgstr "no s'ha pogut obrir el fitxer de pedaç %s" +#: builtin/log.c msgid "need exactly one range" msgstr "necessita exactament un interval" +#: builtin/log.c msgid "not a range" msgstr "no és un interval" +#: builtin/log.c #, c-format msgid "unable to read branch description file '%s'" msgstr "no es pot llegir el fitxer de descripció de la branca «%s»" +#: builtin/log.c msgid "cover letter needs email format" msgstr "la carta de presentació necessita un format de correu electrònic" +#: builtin/log.c msgid "failed to create cover-letter file" msgstr "s'ha produït un error en crear el fitxer de carta de presentació" +#: builtin/log.c #, c-format msgid "insane in-reply-to: %s" msgstr "in-reply-to boig: %s" +#: builtin/log.c msgid "git format-patch [<options>] [<since> | <revision-range>]" msgstr "git format-patch [<opcions>] [<des-de> | <rang-de-revisions>]" +#: builtin/log.c msgid "two output directories?" msgstr "dos directoris de sortida?" +#: builtin/log.c #, c-format msgid "unknown commit %s" msgstr "comissió desconeguda %s" +#: builtin/log.c builtin/replace.c #, c-format msgid "failed to resolve '%s' as a valid ref" msgstr "s'ha produït un error en resoldre «%s» com a referència và lida" +#: builtin/log.c msgid "could not find exact merge base" msgstr "no s'ha pogut trobar la base exacta de la fusió" +#: builtin/log.c msgid "" "failed to get upstream, if you want to record base commit automatically,\n" "please use git branch --set-upstream-to to track a remote branch.\n" @@ -7632,228 +9818,302 @@ msgstr "" "branca remota. També podeu especificar la comissió base amb --base=<base-" "commit-id> manualment" +#: builtin/log.c msgid "failed to find exact merge base" msgstr "no s'ha pogut trobar la base exacta de la fusió" +#: builtin/log.c msgid "base commit should be the ancestor of revision list" msgstr "la comissió base ha de ser l'avantpassat de la llista de revisions" +#: builtin/log.c msgid "base commit shouldn't be in revision list" msgstr "la comissió base no ha de ser en la llista de revisions" +#: builtin/log.c msgid "cannot get patch id" msgstr "no es pot obtenir l'id del pedaç" +#: builtin/log.c msgid "failed to infer range-diff origin of current series" msgstr "" "no s'ha pogut inferir el rang de diferències d'origen de les sèries actuals" +#: builtin/log.c #, c-format msgid "using '%s' as range-diff origin of current series" msgstr "utilitzant «%s» com a origen de rang de diferències de la sèrie actual" +#: builtin/log.c msgid "use [PATCH n/m] even with a single patch" msgstr "usa [PATCH n/m] fins i tot amb un sol pedaç" +#: builtin/log.c msgid "use [PATCH] even with multiple patches" msgstr "usa [PATCH] fins i tot amb múltiples pedaços" +#: builtin/log.c msgid "print patches to standard out" msgstr "imprimeix els pedaços a la sortida està ndard" +#: builtin/log.c msgid "generate a cover letter" msgstr "genera una carta de presentació" +#: builtin/log.c msgid "use simple number sequence for output file names" msgstr "usa una seqüència de números per als noms dels fitxers de sortida" +#: builtin/log.c msgid "sfx" msgstr "sufix" +#: builtin/log.c msgid "use <sfx> instead of '.patch'" msgstr "usa <sufix> en lloc de «.patch»" +#: builtin/log.c msgid "start numbering patches at <n> instead of 1" msgstr "comença numerant els pedaços a <n> en lloc d'1" +#: builtin/log.c msgid "reroll-count" msgstr "reroll-count" +#: builtin/log.c msgid "mark the series as Nth re-roll" msgstr "marca la sèrie com a l'enèsima llançada" +#: builtin/log.c msgid "max length of output filename" msgstr "mida mà xima del nom del fitxer de sortida" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "useu [RFC PATCH] en comptes de [PATCH]" +#: builtin/log.c +msgid "rfc" +msgstr "rfc" + +#: builtin/log.c +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "afig <rfc> (per defecte «RFC») abans de «PATCH»" +#: builtin/log.c msgid "cover-from-description-mode" msgstr "cover-from-description-mode" +#: builtin/log.c msgid "generate parts of a cover letter based on a branch's description" msgstr "" "genera parts d'una carta de presentació basant-se en la descripció d'una " "branca" +#: builtin/log.c msgid "use branch description from file" msgstr "utilitza la descripció de la branca des del fitxer" +#: builtin/log.c msgid "use [<prefix>] instead of [PATCH]" msgstr "useu [<prefix>] en comptes de [PATCH]" +#: builtin/log.c msgid "store resulting files in <dir>" msgstr "emmagatzema els fitxers resultants a <directori>" +#: builtin/log.c msgid "don't strip/add [PATCH]" msgstr "no despullis/afegeixis [PATCH]" +#: builtin/log.c msgid "don't output binary diffs" msgstr "no emetis diferències binà ries" +#: builtin/log.c msgid "output all-zero hash in From header" msgstr "emet un resum de tots zeros en la capçalera From" +#: builtin/log.c msgid "don't include a patch matching a commit upstream" msgstr "no incloguis pedaços que coincideixin amb comissions a la font" +#: builtin/log.c msgid "show patch format instead of default (patch + stat)" msgstr "" "mostra el format de pedaç en lloc del per defecte (pedaç + estadÃstiques)" +#: builtin/log.c msgid "Messaging" msgstr "Missatgeria" +#: builtin/log.c msgid "header" msgstr "capçalera" +#: builtin/log.c msgid "add email header" msgstr "afegeix una capçalera de correu electrònic" +#: builtin/log.c msgid "email" msgstr "correu electrònic" +#: builtin/log.c msgid "add To: header" msgstr "afegeix la capçalera To:" +#: builtin/log.c msgid "add Cc: header" msgstr "afegeix la capçalera Cc:" +#: builtin/log.c msgid "ident" msgstr "identitat" +#: builtin/log.c msgid "set From address to <ident> (or committer ident if absent)" msgstr "" "estableix l'adreça From a <identitat> (o la identitat del comitent si manca)" +#: builtin/log.c msgid "message-id" msgstr "ID de missatge" +#: builtin/log.c msgid "make first mail a reply to <message-id>" msgstr "fes que el primer missatge sigui una resposta a <ID de missatge>" +#: builtin/log.c msgid "boundary" msgstr "lÃmit" +#: builtin/log.c msgid "attach the patch" msgstr "adjunta el pedaç" +#: builtin/log.c msgid "inline the patch" msgstr "posa el pedaç en el cos" +#: builtin/log.c msgid "enable message threading, styles: shallow, deep" msgstr "habilita l'enfilada de missatges, estils: shallow, deep" +#: builtin/log.c msgid "signature" msgstr "signatura" +#: builtin/log.c msgid "add a signature" msgstr "afegeix una signatura" +#: builtin/log.c msgid "base-commit" msgstr "comissió base" +#: builtin/log.c msgid "add prerequisite tree info to the patch series" msgstr "afegeix la informació d'arbre requerida a la sèrie de pedaços" +#: builtin/log.c msgid "add a signature from a file" msgstr "afegeix una signatura des d'un fitxer" +#: builtin/log.c msgid "don't print the patch filenames" msgstr "no imprimeixis els noms de fitxer del pedaç" +#: builtin/log.c msgid "show progress while generating patches" msgstr "mostra el progrés durant la generació de pedaços" +#: builtin/log.c msgid "show changes against <rev> in cover letter or single patch" msgstr "" -"mostra els canvis contra <rev> a la carta de presentació o a un sol pedaç" +"mostra els canvis contra <revisió> a la carta de presentació o a un sol pedaç" +#: builtin/log.c msgid "show changes against <refspec> in cover letter or single patch" msgstr "" "mostra els canvis contra <refspec> a la carta de presentació o a un sol pedaç" +#: builtin/log.c builtin/range-diff.c msgid "percentage by which creation is weighted" msgstr "percentatge pel qual la creació és ponderada" +#: builtin/log.c msgid "show in-body From: even if identical to the e-mail header" msgstr "" "mostra en el cos el remitent: encara que sigui idèntic a la capçalera del " "correu electrònic" +#: builtin/log.c #, c-format msgid "invalid ident line: %s" msgstr "lÃnia d'identitat no và lida: %s" +#: builtin/log.c msgid "--name-only does not make sense" msgstr "--name-only no té sentit" +#: builtin/log.c msgid "--name-status does not make sense" msgstr "--name-status no té sentit" +#: builtin/log.c msgid "--check does not make sense" msgstr "--check no té sentit" +#: builtin/log.c msgid "--remerge-diff does not make sense" msgstr "--remerge-diff no té sentit" +#: builtin/log.c builtin/submodule--helper.c rerere.c submodule.c #, c-format msgid "could not create directory '%s'" msgstr "no s'ha pogut crear el directori «%s»" +#: builtin/log.c msgid "--interdiff requires --cover-letter or single patch" msgstr "--interdiff requereix --cover-letter o un sol pedaç" +#: builtin/log.c msgid "Interdiff:" msgstr "Interdiff:" +#: builtin/log.c #, c-format msgid "Interdiff against v%d:" msgstr "Interdiff contra v%d:" +#: builtin/log.c msgid "--range-diff requires --cover-letter or single patch" msgstr "--range-diff requereix --cover-letter o un sol pedaç" +#: builtin/log.c msgid "Range-diff:" msgstr "Diferència de l'interval:" +#: builtin/log.c #, c-format msgid "Range-diff against v%d:" msgstr "Diferència de l'interval contra el v%d:" +#: builtin/log.c #, c-format msgid "unable to read signature file '%s'" msgstr "no s'ha pogut llegir el fitxer de signatura «%s»" +#: builtin/log.c msgid "Generating patches" msgstr "S'estan generant els pedaços" +#: builtin/log.c msgid "failed to create output files" msgstr "no s'han pogut crear els fitxers de sortida" +#: builtin/log.c msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]" msgstr "git cherry [-v] [<font> [<cap> [<lÃmit>]]]" +#: builtin/log.c #, c-format msgid "" "Could not find a tracked remote branch, please specify <upstream> manually.\n" @@ -7861,108 +10121,126 @@ msgstr "" "No s'ha pogut trobar una branca remota seguida. Especifiqueu <font> " "manualment.\n" +#: builtin/ls-files.c builtin/ls-tree.c #, c-format msgid "could not get object info about '%s'" msgstr "no s'ha pogut obtenir la informació sobre l'objecte «%s»" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "format incorrecte del ls-files: l'element «%s» no comença amb «(»" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "format incorrecte del ls-files: l'element «%s» no acaba amb «)»" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "format incorrecte de ls-files: %%%.*s" - +#: builtin/ls-files.c msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<opcions>] [<fitxer>...]" +#: builtin/ls-files.c builtin/merge-tree.c msgid "separate paths with the NUL character" msgstr "separa els camins amb el carà cter NUL" +#: builtin/ls-files.c msgid "identify the file status with tags" msgstr "identifica l'estat de fitxer amb etiquetes" +#: builtin/ls-files.c msgid "use lowercase letters for 'assume unchanged' files" msgstr "usa lletres minúscules per als fitxers «assume unchanged»" +#: builtin/ls-files.c msgid "use lowercase letters for 'fsmonitor clean' files" msgstr "usa lletres minúscules per als fitxers «fsmonitor clean»" +#: builtin/ls-files.c msgid "show cached files in the output (default)" msgstr "" "mostra en la sortida els fitxers desats en la memòria cau (per defecte)" +#: builtin/ls-files.c msgid "show deleted files in the output" msgstr "mostra en la sortida els fitxers suprimits" +#: builtin/ls-files.c msgid "show modified files in the output" msgstr "mostra en la sortida els fitxers modificats" +#: builtin/ls-files.c msgid "show other files in the output" msgstr "mostra en la sortida els altres fitxers" +#: builtin/ls-files.c msgid "show ignored files in the output" msgstr "mostra en la sortida els fitxers ignorats" +#: builtin/ls-files.c msgid "show staged contents' object name in the output" msgstr "mostra en la sortida el nom d'objecte dels continguts «stage»" +#: builtin/ls-files.c msgid "show files on the filesystem that need to be removed" msgstr "mostra els fitxers en el sistema de fitxers que s'han d'eliminar" +#: builtin/ls-files.c msgid "show 'other' directories' names only" msgstr "mostra només els noms dels directoris «other»" +#: builtin/ls-files.c msgid "show line endings of files" msgstr "mostra els terminadors de lÃnia dels fitxers" +#: builtin/ls-files.c msgid "don't show empty directories" msgstr "no mostris els directoris buits" +#: builtin/ls-files.c msgid "show unmerged files in the output" msgstr "mostra en la sortida els fitxers sense fusionar" +#: builtin/ls-files.c msgid "show resolve-undo information" msgstr "mostra la informació de resolució de desfet" +#: builtin/ls-files.c msgid "skip files matching pattern" msgstr "omet els fitxers coincidents amb el patró" +#: builtin/ls-files.c msgid "read exclude patterns from <file>" msgstr "llegeix els patrons des de <fitxer>" +#: builtin/ls-files.c msgid "read additional per-directory exclude patterns in <file>" msgstr "llegeix els patrons addicionals d'exclusió per directori en <fitxer>" +#: builtin/ls-files.c msgid "add the standard git exclusions" msgstr "afegeix les exclusions està ndards de git" +#: builtin/ls-files.c msgid "make the output relative to the project top directory" msgstr "fes que la sortida sigui relativa al directori superior del projecte" +#: builtin/ls-files.c msgid "if any <file> is not in the index, treat this as an error" msgstr "si qualsevol <fitxer> no és en l'Ãndex, tracta-ho com a error" +#: builtin/ls-files.c builtin/merge-tree.c msgid "tree-ish" msgstr "arbre" +#: builtin/ls-files.c msgid "pretend that paths removed since <tree-ish> are still present" msgstr "" "pretén que els camins eliminats després de <arbre> encara siguin presents" +#: builtin/ls-files.c msgid "show debugging data" msgstr "mostra les dades de depuració" +#: builtin/ls-files.c msgid "suppress duplicate entries" msgstr "suprimeix les entrades duplicades" +#: builtin/ls-files.c msgid "show sparse directories in the presence of a sparse index" msgstr "mostra els directoris dispersos en presència d'un Ãndex dispers" +#: builtin/ls-files.c msgid "" "--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " "--eol" @@ -7970,163 +10248,202 @@ msgstr "" "--format no es pot usar amb -s, -o, -k, -t, --resolve-undo, --deduplicate, --" "eol" +#: builtin/ls-remote.c msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" -" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" -" [--symref] [<repository> [<patterns>...]]" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=<clau>]\n" +" [--symref] [<repositori> [<patrons>...]]" +#: builtin/ls-remote.c msgid "do not print remote URL" msgstr "no imprimeixis l'URL remot" +#: builtin/ls-remote.c builtin/rebase.c msgid "exec" msgstr "executable" +#: builtin/ls-remote.c msgid "path of git-upload-pack on the remote host" msgstr "camà a git-upload-pack en la mà quina remota" +#: builtin/ls-remote.c msgid "limit to tags" msgstr "limita a etiquetes" -msgid "limit to heads" -msgstr "limita a «heads»" +# limita-ho? +#: builtin/ls-remote.c +msgid "limit to branches" +msgstr "limita a les branques" + +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "sinònim de «--branches» en desús" +#: builtin/ls-remote.c msgid "do not show peeled tags" msgstr "no mostris les etiquetes pelades" +#: builtin/ls-remote.c msgid "take url.<base>.insteadOf into account" msgstr "tingues en compte url.<base>.insteadOf" +#: builtin/ls-remote.c msgid "exit with exit code 2 if no matching refs are found" msgstr "surt amb codi de sortida 2 si no es troba cap referència coincident" +#: builtin/ls-remote.c msgid "show underlying ref in addition to the object pointed by it" msgstr "mostra la referència subjacent a més de l'objecte que assenyali" +#: builtin/ls-tree.c msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<opcions>] <arbre> [<camÃ>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "format incorrecte del ls-tree: l'element '%s' no comença amb «(»" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "format incorrecte del ls-tree: l'element '%s' no acaba en «(»" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "format incorrecte de ls-tree: %%%.*s" - +#: builtin/ls-tree.c msgid "only show trees" msgstr "mostra només els arbres" +#: builtin/ls-tree.c msgid "recurse into subtrees" msgstr "inclou recursivament als subarbres" +#: builtin/ls-tree.c msgid "show trees when recursing" msgstr "mostra els arbres quan es treballa recursivament" +#: builtin/ls-tree.c msgid "terminate entries with NUL byte" msgstr "acaba les entrades amb un octet NUL" +#: builtin/ls-tree.c msgid "include object size" msgstr "mida de l'objecte d'inclusió" +#: builtin/ls-tree.c msgid "list only filenames" msgstr "llista només els noms de fitxer" +#: builtin/ls-tree.c msgid "list only objects" msgstr "llista només els objectes" +#: builtin/ls-tree.c msgid "use full path names" msgstr "usa els noms de camà complets" +#: builtin/ls-tree.c msgid "list entire tree; not just current directory (implies --full-name)" msgstr "" "llista l'arbre sencer; no només el directori actual (implica --full-name)" +#: builtin/ls-tree.c msgid "--format can't be combined with other format-altering options" msgstr "--format no es pot combinar amb altres opcions d'alteració de format" #. TRANSLATORS: keep <> in "<" mail ">" info. +#: builtin/mailinfo.c msgid "git mailinfo [<options>] <msg> <patch> < mail >info" msgstr "git mailinfo [<opcions>] <msg> <pedaç> < mail >info" +#: builtin/mailinfo.c msgid "keep subject" msgstr "mantén l'assumpte" +#: builtin/mailinfo.c msgid "keep non patch brackets in subject" msgstr "mantén els parèntesis que no són del pedaç en l'assumpte" +#: builtin/mailinfo.c msgid "copy Message-ID to the end of commit message" msgstr "copia el Message-ID al final del missatge de comissió" +#: builtin/mailinfo.c msgid "re-code metadata to i18n.commitEncoding" msgstr "torna a codificar les metadades a i18n.commitEncoding" +#: builtin/mailinfo.c msgid "disable charset re-coding of metadata" msgstr "inhabilita la recodificació del joc de carà cters de les metadades" +#: builtin/mailinfo.c msgid "encoding" msgstr "codificació" +#: builtin/mailinfo.c msgid "re-code metadata to this encoding" msgstr "recodifica les metadades en aquesta codificació" +#: builtin/mailinfo.c msgid "use scissors" msgstr "usa les tisores" +#: builtin/mailinfo.c msgid "<action>" msgstr "<acció>" +#: builtin/mailinfo.c msgid "action when quoted CR is found" msgstr "acció quan es troba un CR entre cometes" +#: builtin/mailinfo.c msgid "use headers in message's body" msgstr "utilitza les capçaleres en el cos del missatge" +#: builtin/mailsplit.c msgid "reading patches from stdin/tty..." msgstr "s'estan llegint pedaços de stdin/tty..." +#: builtin/mailsplit.c #, c-format msgid "empty mbox: '%s'" msgstr "mbox buit: «%s»" +#: builtin/merge-base.c msgid "git merge-base [-a | --all] <commit> <commit>..." msgstr "git merge-base [-a | --all] <comissió> <comissió>..." +#: builtin/merge-base.c msgid "git merge-base [-a | --all] --octopus <commit>..." msgstr "git merge-base [-a | --all] --octopus <comissió>..." +#: builtin/merge-base.c msgid "git merge-base --is-ancestor <commit> <commit>" msgstr "git merge-base --is-ancestor <comissió> <comissió>" +#: builtin/merge-base.c msgid "git merge-base --independent <commit>..." msgstr "git merge-base --independent <comissió>..." +#: builtin/merge-base.c msgid "git merge-base --fork-point <ref> [<commit>]" msgstr "git merge-base --fork-point <referència> [<comissió>]" +#: builtin/merge-base.c msgid "output all common ancestors" msgstr "emet tots els avantpassats comuns" +#: builtin/merge-base.c msgid "find ancestors for a single n-way merge" msgstr "troba els avantpassats per a una sola fusió d'n vies" +#: builtin/merge-base.c msgid "list revs not reachable from others" msgstr "llista les revisions no abastables d'altres" +#: builtin/merge-base.c msgid "is the first one ancestor of the other?" msgstr "és la primera un avantpassat de l'altre?" +#: builtin/merge-base.c msgid "find where <commit> forked from reflog of <ref>" msgstr "" "troba on <comissió> s'ha bifurcat del registre de referències de <referència>" +#: builtin/merge-file.c msgid "" "git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> " "<orig-file> <file2>" @@ -8134,269 +10451,342 @@ msgstr "" "git merge-file [<opcions>] [-L <nom1> [-L <original> [-L <nom2>]]] <fitxer1> " "<fitxer-original> <fitxer2>" +#: builtin/merge-file.c diff.c msgid "" "option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " "\"histogram\"" msgstr "" "l'opció diff-algorithm accepta «myers», «minimal», «patience» i «histogram»" +#: builtin/merge-file.c msgid "send results to standard output" msgstr "envia els resultats a la sortida està ndard" +#: builtin/merge-file.c msgid "use object IDs instead of filenames" msgstr "utilitza els ID dels objectes en comptes dels noms de fitxer" +#: builtin/merge-file.c msgid "use a diff3 based merge" msgstr "usa una fusió basada en diff3" +#: builtin/merge-file.c msgid "use a zealous diff3 based merge" msgstr "usa una fusió basada en zealous diff3" -msgid "for conflicts, use our version" -msgstr "en conflictes, usa la nostra versió" - -msgid "for conflicts, use their version" -msgstr "en conflictes, usa la seva versió" - -msgid "for conflicts, use a union version" -msgstr "en conflictes, usa una versió d'unió" - +#: builtin/merge-file.c diff.c msgid "<algorithm>" msgstr "<algorisme>" +#: builtin/merge-file.c diff.c msgid "choose a diff algorithm" msgstr "trieu un algorisme per al diff" +#: builtin/merge-file.c msgid "for conflicts, use this marker size" msgstr "en conflictes, usa aquesta mida de marcador" +#: builtin/merge-file.c msgid "do not warn about conflicts" msgstr "no avisis de conflictes" +#: builtin/merge-file.c msgid "set labels for file1/orig-file/file2" msgstr "estableix les etiquetes per a fitxer1/fitxer-original/fitxer2" +#: builtin/merge-file.c #, c-format msgid "object '%s' does not exist" msgstr "l'objecte «%s» no existeix" +#: builtin/merge-file.c msgid "Could not write object file" msgstr "No s'ha pogut escriure el fitxer de l'objecte" +#: builtin/merge-recursive.c #, c-format msgid "unknown option %s" msgstr "opció desconeguda %s" +#: builtin/merge-recursive.c #, c-format msgid "could not parse object '%s'" msgstr "no s'ha pogut analitzar l'objecte «%s»" +#: builtin/merge-recursive.c #, c-format msgid "cannot handle more than %d base. Ignoring %s." msgid_plural "cannot handle more than %d bases. Ignoring %s." msgstr[0] "no es pot gestionar més d'%d base. S'està ignorant %s." msgstr[1] "no es poden gestionar més de %d bases. S'està ignorant %s." +#: builtin/merge-recursive.c msgid "not handling anything other than two heads merge." msgstr "no s'està gestionant res a part de la fusió de dos caps." +#: builtin/merge-recursive.c #, c-format msgid "could not resolve ref '%s'" msgstr "no s'ha pogut resoldre la referència «%s»" +#: builtin/merge-recursive.c #, c-format msgid "Merging %s with %s\n" msgstr "S'està fusionant %s amb %s\n" +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "no s'ha pogut analitzar com a arbre «%s»" + +#: builtin/merge-tree.c builtin/merge.c msgid "not something we can merge" msgstr "no és quelcom que puguem fusionar" +#: builtin/merge-tree.c builtin/merge.c msgid "refusing to merge unrelated histories" msgstr "s'està refusant fusionar històries no relacionades" +#: builtin/merge-tree.c msgid "failure to merge" msgstr "s'ha produït un error en fusionar" +#: builtin/merge-tree.c msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>" -msgstr "git merge-tree [--write-tree] [<opcions>] <branch1> <branch2>" +msgstr "git merge-tree [--write-tree] [<opcions>] <branca1> <branca2>" +#: builtin/merge-tree.c msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>" -msgstr "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>" +msgstr "git merge-tree [--trivial-merge] <base-tree> <branca1> <branca2>" +#: builtin/merge-tree.c msgid "do a real merge instead of a trivial merge" msgstr "fes una fusió real en lloc d'una fusió trivial" +#: builtin/merge-tree.c msgid "do a trivial merge only" msgstr "fes només una fusió trivial" +#: builtin/merge-tree.c msgid "also show informational/conflict messages" msgstr "també mostra missatges informatius i de conflictes" +#: builtin/merge-tree.c msgid "list filenames without modes/oids/stages" msgstr "llista els noms de fitxer sense modes/oids/stages" +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c msgid "allow merging unrelated histories" msgstr "permet fusionar històries no relacionades" +#: builtin/merge-tree.c msgid "perform multiple merges, one per line of input" msgstr "realitza múltiples fusions, una per lÃnia d'entrada" +#: builtin/merge-tree.c msgid "specify a merge-base for the merge" msgstr "cal especificar una referència base per a la fusió" +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c msgid "option=value" msgstr "opció=valor" +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c msgid "option for selected merge strategy" msgstr "opció per a l'estratègia de fusió seleccionada" +#: builtin/merge-tree.c msgid "--trivial-merge is incompatible with all other options" msgstr "--trivial-merge és incompatible amb totes les altres opcions" +#: builtin/merge-tree.c builtin/merge.c #, c-format msgid "unknown strategy option: -X%s" msgstr "opció d'estratègia desconeguda: -X%s" +#: builtin/merge-tree.c builtin/notes.c #, c-format msgid "malformed input line: '%s'." msgstr "lÃnia d'entrada mal formada: «%s»." +#: builtin/merge-tree.c #, c-format msgid "merging cannot continue; got unclean result of %d" msgstr "la fusió no pot continuar; s'ha obtingut un resultat no net de %d" +#: builtin/merge.c msgid "git merge [<options>] [<commit>...]" msgstr "git merge [<opcions>] [<comissió>...]" +#: builtin/merge.c msgid "switch `m' requires a value" msgstr "l'opció «m» requereix un valor" +#: builtin/merge.c #, c-format msgid "option `%s' requires a value" msgstr "l'opció «%s» requereix un valor" +#: builtin/merge.c #, c-format msgid "Could not find merge strategy '%s'.\n" msgstr "No s'ha pogut trobar l'estratègia de fusió «%s».\n" +#: builtin/merge.c #, c-format msgid "Available strategies are:" msgstr "Les estratègies disponibles són:" +#: builtin/merge.c #, c-format msgid "Available custom strategies are:" msgstr "Les estratègies personalitzades disponibles són:" +#: builtin/merge.c builtin/pull.c msgid "do not show a diffstat at the end of the merge" msgstr "no mostris les estadÃstiques de diferència al final de la fusió" +#: builtin/merge.c builtin/pull.c msgid "show a diffstat at the end of the merge" msgstr "mostra les estadÃstiques de diferència al final de la fusió" +#: builtin/merge.c builtin/pull.c msgid "(synonym to --stat)" msgstr "(sinònim de --stat)" +#: builtin/merge.c builtin/pull.c msgid "add (at most <n>) entries from shortlog to merge commit message" msgstr "" "afegeix (com a mà xim <n>) entrades del registre curt al missatge de comissió " "de fusió" +#: builtin/merge.c builtin/pull.c msgid "create a single commit instead of doing a merge" msgstr "crea una única comissió en lloc de fusionar" +#: builtin/merge.c builtin/pull.c msgid "perform a commit if the merge succeeds (default)" msgstr "realitza una comissió si la fusió té èxit (per defecte)" +#: builtin/merge.c builtin/pull.c msgid "edit message before committing" msgstr "edita el missatge abans de cometre" +#: builtin/merge.c msgid "allow fast-forward (default)" msgstr "permet l'avanç rà pid (per defecte)" +#: builtin/merge.c builtin/pull.c msgid "abort if fast-forward is not possible" msgstr "avorta si l'avanç rà pid no és possible" +#: builtin/merge.c builtin/pull.c msgid "verify that the named commit has a valid GPG signature" msgstr "verifica que la comissió anomenada tingui una signatura GPG và lida" +#: builtin/merge.c builtin/notes.c builtin/pull.c builtin/rebase.c +#: builtin/revert.c msgid "strategy" msgstr "estratègia" +#: builtin/merge.c builtin/pull.c msgid "merge strategy to use" msgstr "estratègia de fusió a usar" +#: builtin/merge.c msgid "merge commit message (for a non-fast-forward merge)" msgstr "missatge de comissió de fusió (per a una fusió no d'avanç rà pid)" +#: builtin/merge.c msgid "use <name> instead of the real target" msgstr "usa <nom> en lloc de destà real" +#: builtin/merge.c msgid "abort the current in-progress merge" msgstr "avorta la fusió en curs actual" +#: builtin/merge.c msgid "--abort but leave index and working tree alone" msgstr "--abort però deixa l'Ãndex i l'arbre de treball intactes" +#: builtin/merge.c msgid "continue the current in-progress merge" msgstr "continua la fusió actual en curs" +#: builtin/merge.c msgid "bypass pre-merge-commit and commit-msg hooks" msgstr "evita els lligams pre-merge-commit i commit-msg" +#: builtin/merge.c msgid "could not run stash." msgstr "no s'ha pogut executar «stash»." +#: builtin/merge.c msgid "stash failed" msgstr "l'«stash» ha fallat" +#: builtin/merge.c #, c-format msgid "not a valid object: %s" msgstr "no és un objecte và lid: %s" +#: builtin/merge.c msgid "read-tree failed" msgstr "read-tree ha fallat" +#: builtin/merge.c msgid "Already up to date. (nothing to squash)" msgstr "Ja està actualitzat. (res a fer «squash»)" +#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c msgid "Already up to date." msgstr "Ja està al dia." +#: builtin/merge.c #, c-format msgid "Squash commit -- not updating HEAD\n" msgstr "Comissió «squash» -- no s'està actualitzant HEAD\n" +#: builtin/merge.c #, c-format msgid "No merge message -- not updating HEAD\n" msgstr "Cap missatge de fusió -- no s'està actualitzant HEAD\n" +#: builtin/merge.c #, c-format msgid "'%s' does not point to a commit" msgstr "«%s» no assenyala una comissió" +#: builtin/merge.c #, c-format msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Cadena branch.%s.mergeoptions incorrecta: %s" +#: builtin/merge.c merge-recursive.c msgid "Unable to write index." msgstr "No s'ha pogut escriure l'Ãndex." +#: builtin/merge.c msgid "Not handling anything other than two heads merge." msgstr "No s'està gestionant res a part de la fusió de dos caps." +#: builtin/merge.c builtin/sparse-checkout.c #, c-format msgid "unable to write %s" msgstr "no s'ha pogut escriure %s" +#: builtin/merge.c #, c-format msgid "Could not read from '%s'" msgstr "No s'ha pogut llegir de «%s»" +#: builtin/merge.c #, c-format msgid "Not committing merge; use 'git commit' to complete the merge.\n" msgstr "" "No s'està cometent la fusió; useu «git commit» per a completar la fusió.\n" +#: builtin/merge.c msgid "" "Please enter a commit message to explain why this merge is necessary,\n" "especially if it merges an updated upstream into a topic branch.\n" @@ -8406,70 +10796,89 @@ msgstr "" "necessà ria, especialment si es fusiona una branca amb funcionalitat nova.\n" "\n" +#: builtin/merge.c msgid "An empty message aborts the commit.\n" msgstr "Un missatge buit interromp la comissió.\n" +# will be ignored → es descartaran? +#: builtin/merge.c #, c-format msgid "" -"Lines starting with '%c' will be ignored, and an empty message aborts\n" +"Lines starting with '%s' will be ignored, and an empty message aborts\n" "the commit.\n" msgstr "" -"Les lÃnies que comencen amb «%c» seran ignorades i un missatge buit " -"interromp la comissió.\n" +"Les lÃnies que comencin amb «%s» s'ignoraran, i un missatge buit\n" +"avorta la comissió.\n" +#: builtin/merge.c msgid "Empty commit message." msgstr "El missatge de comissió és buit." +#: builtin/merge.c #, c-format msgid "Wonderful.\n" msgstr "Meravellós.\n" +#: builtin/merge.c #, c-format msgid "Automatic merge failed; fix conflicts and then commit the result.\n" msgstr "" "La fusió automà tica ha fallat; arregleu els conflictes i després cometeu el " "resultat.\n" +#: builtin/merge.c msgid "No current branch." msgstr "No hi ha cap branca actual." +#: builtin/merge.c msgid "No remote for the current branch." msgstr "No hi ha cap remot per a la branca actual." +#: builtin/merge.c msgid "No default upstream defined for the current branch." msgstr "No hi ha cap font per defecte definida per a la branca actual." +#: builtin/merge.c #, c-format msgid "No remote-tracking branch for %s from %s" msgstr "No hi ha cap branca amb seguiment remot per a %s de %s" +#: builtin/merge.c #, c-format msgid "Bad value '%s' in environment '%s'" msgstr "Valor incorrecte «%s» en l'entorn «%s»" +#: builtin/merge.c editor.c read-cache.c wrapper.c #, c-format msgid "could not close '%s'" msgstr "no s'ha pogut tancar «%s»" +#: builtin/merge.c #, c-format msgid "not something we can merge in %s: %s" msgstr "no és quelcom que puguem fusionar en %s: %s" +#: builtin/merge.c msgid "--abort expects no arguments" msgstr "--abort no espera cap argument" +#: builtin/merge.c msgid "There is no merge to abort (MERGE_HEAD missing)." msgstr "No hi ha fusió a avortar (manca MERGE_HEAD)." +#: builtin/merge.c msgid "--quit expects no arguments" msgstr "--quit no espera cap argument" +#: builtin/merge.c msgid "--continue expects no arguments" msgstr "--continue no espera cap argument" +#: builtin/merge.c msgid "There is no merge in progress (MERGE_HEAD missing)." msgstr "No hi ha cap fusió en curs (manca MERGE_HEAD)." +#: builtin/merge.c msgid "" "You have not concluded your merge (MERGE_HEAD exists).\n" "Please, commit your changes before you merge." @@ -8477,6 +10886,7 @@ msgstr "" "No heu conclòs la vostra fusió (MERGE_HEAD existeix).\n" "Cometeu els vostres canvis abans de fusionar." +#: builtin/merge.c msgid "" "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" "Please, commit your changes before you merge." @@ -8484,31 +10894,39 @@ msgstr "" "No heu conclòs el vostre «cherry pick» (CHERRY_PICK_HEAD existeix).\n" "Cometeu els vostres canvis abans de fusionar." +#: builtin/merge.c msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)." msgstr "No heu conclòs el vostre «cherry pick» (CHERRY_PICK_HEAD existeix)." +#: builtin/merge.c msgid "No commit specified and merge.defaultToUpstream not set." msgstr "" "No hi ha una comissió especificada i merge.defaultToUpstream no està " "establert." +#: builtin/merge.c msgid "Squash commit into empty head not supported yet" msgstr "Una comissió «squash» a una HEAD buida encara no es permet" +#: builtin/merge.c msgid "Non-fast-forward commit does not make sense into an empty head" msgstr "Una comissió no d'avanç rà pid no té sentit a una HEAD buida" +#: builtin/merge.c #, c-format msgid "%s - not something we can merge" msgstr "%s - no és una cosa que puguem fusionar" +#: builtin/merge.c msgid "Can merge only exactly one commit into empty head" msgstr "Es pot fusionar només una comissió a una HEAD buida" +#: builtin/merge.c #, c-format msgid "Updating %s..%s\n" msgstr "S'estan actualitzant %s..%s\n" +#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -8517,126 +10935,159 @@ msgstr "" "Els canvis locals als fitxers següents se sobreescriuran per la fusió:\n" " %s" +#: builtin/merge.c #, c-format msgid "Trying really trivial in-index merge...\n" msgstr "S'està intentant una fusió molt trivial en l'Ãndex...\n" +#: builtin/merge.c #, c-format msgid "Nope.\n" msgstr "No.\n" +#: builtin/merge.c #, c-format msgid "Rewinding the tree to pristine...\n" msgstr "S'està rebobinant l'arbre a la pristina...\n" +#: builtin/merge.c #, c-format msgid "Trying merge strategy %s...\n" msgstr "S'està intentant l'estratègia de fusió %s...\n" +#: builtin/merge.c #, c-format msgid "No merge strategy handled the merge.\n" msgstr "Cap estratègia de fusió ha gestionat la fusió.\n" +#: builtin/merge.c #, c-format msgid "Merge with strategy %s failed.\n" msgstr "L'estratègia de fusió %s ha fallat.\n" +#: builtin/merge.c #, c-format msgid "Using the %s strategy to prepare resolving by hand.\n" msgstr "S'està usant l'estratègia %s per a preparar la resolució a mà .\n" +#: builtin/merge.c #, c-format msgid "Automatic merge went well; stopped before committing as requested\n" msgstr "" "La fusió automà tica ha sortit bé; s'ha aturat abans de cometre com s'havia " "demanat\n" +#: builtin/merge.c #, c-format msgid "When finished, apply stashed changes with `git stash pop`\n" msgstr "Quan acabi, aplica els canvis «stashed» amb «git stash pop»\n" +#: builtin/mktag.c #, c-format msgid "warning: tag input does not pass fsck: %s" msgstr "avÃs: l'entrada d'etiqueta no passa fsck: %s" +#: builtin/mktag.c #, c-format msgid "error: tag input does not pass fsck: %s" msgstr "error: l'entrada d'etiqueta no passa fsck: %s" +#: builtin/mktag.c #, c-format msgid "%d (FSCK_IGNORE?) should never trigger this callback" msgstr "%d (FSCK_IGNORE?) no hauria d'activar mai aquesta crida de retorn" +#: builtin/mktag.c #, c-format msgid "could not read tagged object '%s'" msgstr "no s'ha pogut llegir l'objecte etiquetat «%s»" +#: builtin/mktag.c #, c-format msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "l'objecte «%s» s'ha etiquetat com a «%s», però és del tipus «%s»" -msgid "could not read from stdin" -msgstr "no s'ha pogut llegir des de stdin" - +#: builtin/mktag.c msgid "tag on stdin did not pass our strict fsck check" msgstr "l'etiqueta a stdin no ha passat la comprovació estricta del fsck" +#: builtin/mktag.c msgid "tag on stdin did not refer to a valid object" msgstr "l'etiqueta a stdin no apunta a un objecte và lid" +#: builtin/mktag.c builtin/tag.c msgid "unable to write tag file" msgstr "no s'ha pogut escriure el fitxer d'etiqueta" +#: builtin/mktree.c msgid "input is NUL terminated" msgstr "l'entrada és acabada amb NUL" +#: builtin/mktree.c builtin/write-tree.c msgid "allow missing objects" msgstr "permet els objectes absents" +#: builtin/mktree.c msgid "allow creation of more than one tree" msgstr "permet la creació de més d'un arbre" +#: builtin/multi-pack-index.c msgid "" "git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-" "snapshot=<path>]" msgstr "" -"git multi-pack-index [<opcions>] write [--preferred-pack=<pack>][--refs-" +"git multi-pack-index [<opcions>] write [--preferred-pack=<paquet>][--refs-" "snapshot=<camÃ>]" +#: builtin/multi-pack-index.c msgid "git multi-pack-index [<options>] verify" msgstr "git multi-pack-index [<opcions>] verify" +#: builtin/multi-pack-index.c msgid "git multi-pack-index [<options>] expire" msgstr "git multi-pack-index [<opcions>] expire" +#: builtin/multi-pack-index.c msgid "git multi-pack-index [<options>] repack [--batch-size=<size>]" msgstr "git multi-pack-index [<opcions>] repack [--batch-size=<mida>]" +#: builtin/multi-pack-index.c msgid "directory" msgstr "directori" +#: builtin/multi-pack-index.c msgid "object directory containing set of packfile and pack-index pairs" msgstr "" "directori de l'objecte que conté el conjunt de parells de fitxers i Ãndexs " "de paquets" +#: builtin/multi-pack-index.c msgid "preferred-pack" msgstr "paquet preferit" +#: builtin/multi-pack-index.c msgid "pack for reuse when computing a multi-pack bitmap" msgstr "" "empaqueta per a reutilitzar quan es calcula un mapa de bits multipaquet" +#: builtin/multi-pack-index.c msgid "write multi-pack bitmap" msgstr "escriu un map de bits multipaquet" +#: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "escriu un nou MIDX incremental" + +#: builtin/multi-pack-index.c msgid "write multi-pack index containing only given indexes" msgstr "escriu un Ãndex multipaquet que contingui només els Ãndexs donats" +#: builtin/multi-pack-index.c msgid "refs snapshot for selecting bitmap commits" msgstr "" "instantà nia de referències per a seleccionar les comissions de mapa de bits" +#: builtin/multi-pack-index.c msgid "" "during repack, collect pack-files of smaller size into a batch that is " "larger than this size" @@ -8644,245 +11095,309 @@ msgstr "" "durant el reempaquetament, recull els fitxers de paquets de mida més petita " "en un lot que és més gran que aquesta mida" +#: builtin/mv.c msgid "git mv [<options>] <source>... <destination>" msgstr "git mv [<opcions>] <origen>... <destÃ>" +#: builtin/mv.c #, c-format msgid "Directory %s is in index and no submodule?" msgstr "El directori %s és en l'Ãndex i no hi ha cap submòdul?" +#: builtin/mv.c msgid "Please stage your changes to .gitmodules or stash them to proceed" msgstr "" "Feu «stage» dels vostres canvis a .gitmodules o feu «stash» dels mateixos " "per a procedir" +#: builtin/mv.c #, c-format msgid "%.*s is in index" msgstr "%.*s és en l'Ãndex" +#: builtin/mv.c msgid "force move/rename even if target exists" msgstr "força el moviment / canvi de nom encara que el destà existeixi" +#: builtin/mv.c msgid "skip move/rename errors" msgstr "omet els errors de moviment / canvi de nom" +#: builtin/mv.c #, c-format msgid "destination '%s' is not a directory" msgstr "el destà «%s» no és un directori" +#: builtin/mv.c #, c-format msgid "Checking rename of '%s' to '%s'\n" msgstr "S'està comprovant el canvi de nom de «%s» a «%s»\n" +#: builtin/mv.c msgid "bad source" msgstr "origen incorrecte" +#: builtin/mv.c msgid "destination exists" msgstr "el destà existeix" +#: builtin/mv.c msgid "can not move directory into itself" msgstr "no es pot moure un directori a dins d'ell mateix" +#: builtin/mv.c msgid "destination already exists" msgstr "la destinació ja existeix" +#: builtin/mv.c msgid "source directory is empty" msgstr "el directori d'origen està buit" +#: builtin/mv.c msgid "not under version control" msgstr "no està sota control de versions" +#: builtin/mv.c msgid "conflicted" msgstr "en conflicte" +#: builtin/mv.c #, c-format msgid "overwriting '%s'" msgstr "s'està sobreescrivint «%s»" +#: builtin/mv.c msgid "Cannot overwrite" msgstr "No es pot sobreescriure" +#: builtin/mv.c msgid "multiple sources for the same target" msgstr "múltiples orÃgens per al mateix destÃ" +#: builtin/mv.c msgid "destination directory does not exist" msgstr "el directori destà no existeix" +#: builtin/mv.c msgid "destination exists in the index" msgstr "el destà existeix a l'Ãndex" +#: builtin/mv.c #, c-format msgid "%s, source=%s, destination=%s" msgstr "%s, origen=%s, destÃ=%s" +#: builtin/mv.c #, c-format msgid "Renaming %s to %s\n" msgstr "S'està canviant el nom de %s a %s\n" +#: builtin/mv.c builtin/remote.c #, c-format msgid "renaming '%s' failed" msgstr "el canvi del nom de «%s» ha fallat" +#: builtin/name-rev.c msgid "git name-rev [<options>] <commit>..." msgstr "git name-rev [<opcions>] <comissió>..." +#: builtin/name-rev.c msgid "git name-rev [<options>] --all" msgstr "git name-rev [<opcions>] --all" +#: builtin/name-rev.c msgid "git name-rev [<options>] --annotate-stdin" msgstr "git name-rev [<opcions>] --annotate-stdin" +#: builtin/name-rev.c msgid "print only ref-based names (no object names)" msgstr "imprimeix només els noms basats en referències (no els noms d'objecte)" +#: builtin/name-rev.c msgid "only use tags to name the commits" msgstr "només usa les etiquetes per a anomenar les comissions" +#: builtin/name-rev.c msgid "only use refs matching <pattern>" msgstr "només usa les referències que coincideixin amb <patró>" +#: builtin/name-rev.c msgid "ignore refs matching <pattern>" msgstr "ignora les referències que coincideixin amb <patró>" +#: builtin/name-rev.c msgid "list all commits reachable from all refs" msgstr "llista totes les comissions abastables de totes les referències" +#: builtin/name-rev.c msgid "deprecated: use --annotate-stdin instead" msgstr "obsolet: useu en comptes --annotate-stdin" +#: builtin/name-rev.c msgid "annotate text from stdin" msgstr "anota el text de stdin" +#: builtin/name-rev.c msgid "allow to print `undefined` names (default)" msgstr "permet imprimir els noms «undefined» (per defecte)" +#: builtin/name-rev.c msgid "dereference tags in the input (internal use)" msgstr "desreferencia les etiquetes en l'entrada (ús intern)" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] [list [<object>]]" msgstr "git notes [--ref <referència-de-notes>] [llista [<objecte>]]" +#: builtin/notes.c msgid "" "git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--" "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " "| -C) <object>] [<object>]" msgstr "" "git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--" -"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " -"| -C) <object>] [<object>]" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <fitxer> | (-" +"c | -C) <object>] [<object>]" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>" msgstr "" -"git notes [--ref <referència-de-notes>] copy [-f] <d'objecte> <a-objecte>" +"git notes [--ref <referència-de-notes>] copy [-f] <objecte-de> <objecte-a>" +#: builtin/notes.c msgid "" "git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--" "separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " "| -C) <object>] [<object>]" msgstr "" "git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--" -"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " -"| -C) <object>] [<object>]" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <fitxer> | (-" +"c | -C) <objecte>] [<objecte>]" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" msgstr "" "git notes [--ref <referència-de-notes>] edit [--allow-empty] [<objecte>]" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] show [<object>]" msgstr "git notes [--ref <referència-de-notes>] show [<objecte>]" +#: builtin/notes.c msgid "" "git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>" msgstr "" "git notes [--ref <referència-de-notes>] merge [-v | -q] [-s <estratègia>] " "<referència-de-notes>" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] remove [<object>...]" msgstr "git notes [--ref <referència-de-notes>] remove [<objecte>...]" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] prune [-n] [-v]" msgstr "git notes [--ref <referència-de-notes>] prune [-n] [-v]" +#: builtin/notes.c msgid "git notes [--ref <notes-ref>] get-ref" msgstr "git notes [--ref <referència-de-notes>] get-ref" +#: builtin/notes.c msgid "git notes [list [<object>]]" msgstr "git notes [llista [<objecte>]]" +#: builtin/notes.c msgid "git notes add [<options>] [<object>]" msgstr "git notes add [<opcions>] [<objecte>]" +#: builtin/notes.c msgid "git notes copy [<options>] <from-object> <to-object>" -msgstr "git notes copy [<opcions>] <d'objecte> <a-objecte>" +msgstr "git notes copy [<opcions>] <objecte-de> <objecte-a>" +#: builtin/notes.c msgid "git notes copy --stdin [<from-object> <to-object>]..." -msgstr "git notes copy --stdin [<d'objecte> <a-objecte>]..." +msgstr "git notes copy --stdin [<objecte-de> <objecte-a>]..." +#: builtin/notes.c msgid "git notes append [<options>] [<object>]" msgstr "git notes append [<opcions>] [<objecte>]" +#: builtin/notes.c msgid "git notes edit [<object>]" msgstr "git notes edit [<objecte>]" +#: builtin/notes.c msgid "git notes show [<object>]" msgstr "git notes show [<objecte>]" +#: builtin/notes.c msgid "git notes merge [<options>] <notes-ref>" msgstr "git notes merge [<opcions>] <referència-de-notes>" +#: builtin/notes.c msgid "git notes merge --commit [<options>]" msgstr "git notes merge --commit [<opcions>]" +#: builtin/notes.c msgid "git notes merge --abort [<options>]" msgstr "git notes merge --abort [<opcions>]" +#: builtin/notes.c msgid "git notes remove [<object>]" msgstr "git notes remove [<objecte>]" +#: builtin/notes.c msgid "git notes prune [<options>]" msgstr "git notes prune [<opcions>]" +#: builtin/notes.c msgid "Write/edit the notes for the following object:" msgstr "Escriviu/editeu les notes per l'objecte següent:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "no s'ha pogut iniciar «show» per a l'objecte «%s»" - +#: builtin/notes.c msgid "could not read 'show' output" msgstr "no s'ha pogut llegir la sortida de «show»" +#: builtin/notes.c #, c-format msgid "failed to finish 'show' for object '%s'" msgstr "s'ha produït un error en finalitzar «show» per a l'objecte «%s»" +#: builtin/notes.c msgid "please supply the note contents using either -m or -F option" msgstr "" "especifiqueu el contingut de la nota fent servir l'opció -m o l'opció -F" +#: builtin/notes.c msgid "unable to write note object" msgstr "no s'ha pogut escriure l'objecte de nota" +#: builtin/notes.c #, c-format msgid "the note contents have been left in %s" msgstr "s'han deixat els continguts de la nota en %s" +#: builtin/notes.c builtin/tag.c #, c-format msgid "could not open or read '%s'" msgstr "no s'ha pogut obrir o llegir «%s»" +#: builtin/notes.c #, c-format msgid "failed to resolve '%s' as a valid ref." msgstr "s'ha produït un error en resoldre «%s» com a referència và lida." +#: builtin/notes.c #, c-format msgid "failed to read object '%s'." msgstr "s'ha produït un error en llegir l'objecte «%s»." +#: builtin/notes.c #, c-format msgid "cannot read note data from non-blob object '%s'." msgstr "no es poden llegir les dades de node de l'objecte no de blob «%s»." +#: builtin/notes.c #, c-format msgid "failed to copy notes from '%s' to '%s'" msgstr "s'ha produït un error en copiar les notes de «%s» a «%s»" @@ -8890,41 +11405,53 @@ msgstr "s'ha produït un error en copiar les notes de «%s» a «%s»" #. TRANSLATORS: the first %s will be replaced by a git #. notes command: 'add', 'merge', 'remove', etc. #. +#: builtin/notes.c #, c-format msgid "refusing to %s notes in %s (outside of refs/notes/)" msgstr "s'està refusant %s les notes en %s (fora de refs/notes/)" +#: builtin/notes.c #, c-format msgid "no note found for object %s." msgstr "no s'ha trobat cap nota per a l'objecte %s." +#: builtin/notes.c msgid "note contents as a string" msgstr "anota els continguts com a cadena" +#: builtin/notes.c msgid "note contents in a file" msgstr "anota els continguts en un fitxer" +#: builtin/notes.c msgid "reuse and edit specified note object" msgstr "reusa i edita l'objecte de nota especificat" +#: builtin/notes.c msgid "reuse specified note object" msgstr "reusa l'objecte de nota especificat" +#: builtin/notes.c msgid "allow storing empty note" msgstr "permet l'emmagatzematge d'una nota buida" +#: builtin/notes.c msgid "replace existing notes" msgstr "reemplaça les notes existents" +#: builtin/notes.c msgid "<paragraph-break>" msgstr "<paragraph-break>" +#: builtin/notes.c msgid "insert <paragraph-break> between paragraphs" msgstr "insereix <paragraph-break> entre parà grafs" +#: builtin/notes.c msgid "remove unnecessary whitespace" msgstr "elimina l'espai en blanc innecessari" +#: builtin/notes.c #, c-format msgid "" "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -8933,24 +11460,30 @@ msgstr "" "No es poden afegir les notes. S'han trobat notes existents de l'objecte %s. " "Useu «-f» per a sobreescriure les notes existents" +#: builtin/notes.c #, c-format msgid "Overwriting existing notes for object %s\n" msgstr "S'estan sobreescrivint les notes existents de l'objecte %s\n" +#: builtin/notes.c #, c-format msgid "Removing note for object %s\n" msgstr "S'està eliminant la nota de l'objecte %s\n" +#: builtin/notes.c msgid "read objects from stdin" msgstr "llegeix els objectes des de stdin" +#: builtin/notes.c msgid "load rewriting config for <command> (implies --stdin)" msgstr "" "carrega la configuració de reescriptura per a <ordre> (implica --stdin)" +#: builtin/notes.c msgid "too few arguments" msgstr "massa pocs arguments" +#: builtin/notes.c #, c-format msgid "" "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -8959,10 +11492,12 @@ msgstr "" "No es poden copiar les notes. S'han trobat notes existents de l'objecte %s. " "Useu «-f» per a sobreescriure les notes existents" +#: builtin/notes.c #, c-format msgid "missing notes on source object %s. Cannot copy." msgstr "manquen notes a l'objecte font %s. No es pot copiar." +#: builtin/notes.c #, c-format msgid "" "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n" @@ -8971,41 +11506,53 @@ msgstr "" "Es desaconsellen les opcions -m/-F/-c/-C en favor de la subordre «edit».\n" "Useu «git notes add -f -m/-F/-c/-C» en lloc d'això.\n" +#: builtin/notes.c msgid "failed to delete ref NOTES_MERGE_PARTIAL" msgstr "s'ha produït un error en suprimir la referència NOTES_MERGE_PARTIAL" +#: builtin/notes.c msgid "failed to delete ref NOTES_MERGE_REF" msgstr "s'ha produït un error en suprimir la referència NOTES_MERGE_REF" +#: builtin/notes.c msgid "failed to remove 'git notes merge' worktree" msgstr "" "s'ha produït un error en eliminar l'arbre de treball de «git notes merge»" +#: builtin/notes.c msgid "failed to read ref NOTES_MERGE_PARTIAL" msgstr "s'ha produït un error en llegir la referència NOTES_MERGE_PARTIAL" +#: builtin/notes.c msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "no s'ha pogut trobar cap comissió de NOTES_MERGE_PARTIAL." +#: builtin/notes.c msgid "could not parse commit from NOTES_MERGE_PARTIAL." msgstr "no s'ha pogut analitzar la comissió de NOTES_MERGE_PARTIAL." +#: builtin/notes.c msgid "failed to resolve NOTES_MERGE_REF" msgstr "s'ha produït un error en resoldre NOTES_MERGE_REF" +#: builtin/notes.c msgid "failed to finalize notes merge" msgstr "s'ha produït un error en finalitzar la fusió de notes" +#: builtin/notes.c #, c-format msgid "unknown notes merge strategy %s" msgstr "estratègia de fusió de notes desconeguda %s" +#: builtin/notes.c msgid "General options" msgstr "Opcions generals" +#: builtin/notes.c msgid "Merge options" msgstr "Opcions de fusió" +#: builtin/notes.c msgid "" "resolve notes conflicts using the given strategy (manual/ours/theirs/union/" "cat_sort_uniq)" @@ -9013,38 +11560,48 @@ msgstr "" "resol els conflictes de nota usant l'estratègia donada (manual/ours/theirs/" "union/cat_sort_uniq)" +#: builtin/notes.c msgid "Committing unmerged notes" msgstr "S'estan cometent les notes sense fusionar" +#: builtin/notes.c msgid "finalize notes merge by committing unmerged notes" msgstr "finalitza la fusió de notes cometent les notes sense fusionar" +#: builtin/notes.c msgid "Aborting notes merge resolution" msgstr "S'està avortant la resolució de fusió de notes" +#: builtin/notes.c msgid "abort notes merge" msgstr "avorta la fusió de notes" +#: builtin/notes.c msgid "cannot mix --commit, --abort or -s/--strategy" msgstr "no es pot combinar --commit, --abort i -s/--strategy" +#: builtin/notes.c msgid "must specify a notes ref to merge" msgstr "cal especificar una referència de notes a fusionar" +#: builtin/notes.c #, c-format msgid "unknown -s/--strategy: %s" msgstr "-s/--strategy desconeguda: %s" +#: builtin/notes.c #, c-format msgid "a notes merge into %s is already in-progress at %s" msgstr "una fusió de notes a %s ja està en curs a %s" +#: builtin/notes.c #, c-format msgid "failed to store link to current notes ref (%s)" msgstr "" "s'ha produït un error en emmagatzemar l'enllaç a la referència de notes " "actual (%s)" +#: builtin/notes.c #, c-format msgid "" "Automatic notes merge failed. Fix conflicts in %s and commit the result with " @@ -9055,44 +11612,56 @@ msgstr "" "cometeu el resultat amb «git notes merge --commit», o avorteu la fusió amb " "«git notes merge --abort».\n" +#: builtin/notes.c builtin/tag.c #, c-format msgid "Failed to resolve '%s' as a valid ref." msgstr "S'ha produït un error en resoldre «%s» com a referència và lida." +#: builtin/notes.c #, c-format msgid "Object %s has no note\n" msgstr "L'objecte %s no té cap nota\n" +#: builtin/notes.c msgid "attempt to remove non-existent note is not an error" msgstr "l'intent d'eliminar una nota no existent no és un error" +#: builtin/notes.c msgid "read object names from the standard input" msgstr "llegeix els noms d'objecte des de l'entrada està ndard" +#: builtin/notes.c builtin/prune.c builtin/worktree.c msgid "do not remove, show only" msgstr "no eliminis, només mostra" +#: builtin/notes.c msgid "report pruned notes" msgstr "informa de notes podades" +#: builtin/notes.c msgid "notes-ref" msgstr "referència de notes" +#: builtin/notes.c msgid "use notes from <notes-ref>" msgstr "usa les notes de <referència-de-notes>" +#: builtin/notes.c builtin/remote.c parse-options.c #, c-format msgid "unknown subcommand: `%s'" msgstr "subordre desconeguda: «%s»" +#: builtin/pack-objects.c msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]" msgstr "git pack-objects --stdout [<opcions>] [< <ref-list> | < <object-list>]" +#: builtin/pack-objects.c msgid "" "git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]" msgstr "" "git pack-objects [<opcions>] <base-name> [< <ref-list> | < <object-list>]" +#: builtin/pack-objects.c #, c-format msgid "" "write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " @@ -9101,108 +11670,135 @@ msgstr "" "write_reuse_object: no s'ha pogut localitzar %s, s'esperava a la posició " "%<PRIuMAX> al paquet %s" +#: builtin/pack-objects.c #, c-format msgid "bad packed object CRC for %s" msgstr "CRC de l'objecte empaquetat malmès per a %s" +#: builtin/pack-objects.c #, c-format msgid "corrupt packed object for %s" msgstr "objecte empaquetat corrupte per a %s" +#: builtin/pack-objects.c #, c-format msgid "recursive delta detected for object %s" msgstr "diferència recursiva detectada per a l'objecte %s" +#: builtin/pack-objects.c #, c-format msgid "ordered %u objects, expected %<PRIu32>" msgstr "ordenats %u objectes, s'esperaven %<PRIu32>" +#: builtin/pack-objects.c #, c-format msgid "expected object at offset %<PRIuMAX> in pack %s" msgstr "objecte esperat a la posició %<PRIuMAX> al paquet %s" +#: builtin/pack-objects.c msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit" msgstr "" "s'està inhabilitant l'escriptura de mapes de bits, es divideixen els paquets " "a causa de pack.packSizeLimit" +#: builtin/pack-objects.c msgid "Writing objects" msgstr "S'estan escrivint els objectes" +#: builtin/pack-objects.c builtin/update-index.c #, c-format msgid "failed to stat %s" msgstr "s'ha produït un error en fer stat a %s" +#: builtin/pack-objects.c object-file.c #, c-format msgid "failed utime() on %s" msgstr "ha fallat utime() a %s" +#: builtin/pack-objects.c msgid "failed to write bitmap index" msgstr "s'ha produït un error en escriure l'Ãndex de mapa de bits" +#: builtin/pack-objects.c #, c-format msgid "wrote %<PRIu32> objects while expecting %<PRIu32>" msgstr "escrits %<PRIu32> objectes mentre s'esperaven %<PRIu32>" +#: builtin/pack-objects.c builtin/repack.c msgid "disabling bitmap writing, as some objects are not being packed" msgstr "" "s'està inhabilitant l'escriptura de mapes de bits, perquè alguns objectes no " "s'empaqueten" +#: builtin/pack-objects.c #, c-format msgid "delta base offset overflow in pack for %s" msgstr "desbordament del desplaçament base de diferències en paquet per a %s" +#: builtin/pack-objects.c #, c-format msgid "delta base offset out of bound for %s" msgstr "desplaçament base de diferències fora dels lÃmits per a %s" +#: builtin/pack-objects.c msgid "Counting objects" msgstr "S'estan comptant els objectes" +#: builtin/pack-objects.c pack-bitmap.c #, c-format msgid "unable to get size of %s" msgstr "no s'ha pogut obtenir la mida de %s" +#: builtin/pack-objects.c #, c-format msgid "unable to parse object header of %s" msgstr "no s'ha pogut analitzar la capçalera de l'objecte de %s" +#: builtin/pack-objects.c #, c-format msgid "object %s cannot be read" msgstr "no es pot llegir l'objecte %s" +#: builtin/pack-objects.c #, c-format msgid "object %s inconsistent object length (%<PRIuMAX> vs %<PRIuMAX>)" msgstr "" "l'objecte %s té una longitud d'objecte inconsistent (%<PRIuMAX> vs " "%<PRIuMAX>)" +#: builtin/pack-objects.c msgid "suboptimal pack - out of memory" msgstr "paquet subòptim - sense memòria" +#: builtin/pack-objects.c #, c-format msgid "Delta compression using up to %d threads" msgstr "Compressió de diferències usant fins a %d fils" +#: builtin/pack-objects.c #, c-format msgid "unable to pack objects reachable from tag %s" msgstr "no s'han pogut empaquetar els objectes abastables des de l'etiqueta %s" +#: builtin/pack-objects.c commit-graph.c #, c-format msgid "unable to get type of object %s" msgstr "no s'ha pogut obtenir el tipus de l'objecte: %s" +#: builtin/pack-objects.c msgid "Compressing objects" msgstr "S'estan comprimint els objectes" +#: builtin/pack-objects.c msgid "inconsistency with delta count" msgstr "inconsistència amb el comptador de diferències" +#: builtin/pack-objects.c #, c-format msgid "invalid pack.allowPackReuse value: '%s'" msgstr "valor pack.allowPackReuse value no và lid: «%s»" +#: builtin/pack-objects.c #, c-format msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" @@ -9211,6 +11807,7 @@ msgstr "" "el valor de uploadpack.blobpackfileuri ha de tenir la forma «<object-hash> " "<pack-hash> <uri>» (s'ha rebut «%s»)" +#: builtin/pack-objects.c #, c-format msgid "" "object already configured in another uploadpack.blobpackfileuri (got '%s')" @@ -9218,27 +11815,34 @@ msgstr "" "l'objecte ja està configurat en un altre uploadpack.blobpackfileuri (s'ha " "rebut «%s»)" +#: builtin/pack-objects.c #, c-format msgid "could not get type of object %s in pack %s" msgstr "no s'ha pogut obtenir el tipus de l'objecte %s al paquet %s" +#: builtin/pack-objects.c #, c-format msgid "could not find pack '%s'" msgstr "no s'ha pogut trobar el paquet «%s»" +#: builtin/pack-objects.c #, c-format msgid "packfile %s cannot be accessed" msgstr "no es pot accedir al fitxer de paquet %s" +#: builtin/pack-objects.c msgid "Enumerating cruft objects" msgstr "S'estan enumerant els objectes superflus" +#: builtin/pack-objects.c msgid "unable to add cruft objects" msgstr "no s'han pogut afegir els objectes superflus" +#: builtin/pack-objects.c msgid "Traversing cruft objects" msgstr "S'estan recorrent els objectes superflus" +#: builtin/pack-objects.c #, c-format msgid "" "expected edge object ID, got garbage:\n" @@ -9247,6 +11851,7 @@ msgstr "" "s'esperava un identificador vora de l'objecte, s'ha rebut brossa:\n" " %s" +#: builtin/pack-objects.c #, c-format msgid "" "expected object ID, got garbage:\n" @@ -9255,216 +11860,280 @@ msgstr "" "s'esperava un identificador d'objecte, s'ha rebut brossa:\n" " %s" +#: builtin/pack-objects.c reachable.c msgid "could not load cruft pack .mtimes" msgstr "no s'ha pogut carregar superflus del paquet superflu" +#: builtin/pack-objects.c msgid "cannot open pack index" msgstr "no s'ha pogut obrir l'Ãndex del paquet" +#: builtin/pack-objects.c #, c-format msgid "loose object at %s could not be examined" msgstr "no s'ha pogut examinar l'objecte solt a %s" +#: builtin/pack-objects.c msgid "unable to force loose object" msgstr "no s'ha pogut forçar l'objecte solt" +#: builtin/pack-objects.c #, c-format msgid "not a rev '%s'" msgstr "«%s» no és una revisió" +#: builtin/pack-objects.c builtin/rev-parse.c #, c-format msgid "bad revision '%s'" msgstr "revisió incorrecta «%s»" +#: builtin/pack-objects.c msgid "unable to add recent objects" msgstr "no s'han pogut afegir els objectes recents" +#: builtin/pack-objects.c #, c-format msgid "unsupported index version %s" msgstr "versió d'Ãndex no compatible %s" +#: builtin/pack-objects.c #, c-format msgid "bad index version '%s'" msgstr "versió d'Ãndex incorrecta «%s»" +#: builtin/pack-objects.c msgid "show progress meter during object writing phase" msgstr "mostra l'indicador de progrés durant la fase d'escriptura d'objectes" +#: builtin/pack-objects.c msgid "similar to --all-progress when progress meter is shown" msgstr "similar a --all-progress quan l'indicador de progrés es mostra" +#: builtin/pack-objects.c msgid "<version>[,<offset>]" msgstr "<versió>[,<desplaçament>]" +#: builtin/pack-objects.c msgid "write the pack index file in the specified idx format version" msgstr "" "escriu el fitxer d'Ãndex de paquet en la versió de format d'Ãndex " "especificada" +#: builtin/pack-objects.c msgid "maximum size of each output pack file" msgstr "mida mà xima de cada fitxer empaquetat de sortida" +#: builtin/pack-objects.c msgid "ignore borrowed objects from alternate object store" msgstr "" "ignora els objectes manllevats d'un emmagatzematge d'objectes alternatiu" +#: builtin/pack-objects.c msgid "ignore packed objects" msgstr "ignora els objectes empaquetats" +#: builtin/pack-objects.c msgid "limit pack window by objects" msgstr "limita la finestra d'empaquetament per objectes" +#: builtin/pack-objects.c msgid "limit pack window by memory in addition to object limit" msgstr "" "limita la finestra d'empaquetament per memòria a més del lÃmit d'objectes" +#: builtin/pack-objects.c msgid "maximum length of delta chain allowed in the resulting pack" msgstr "" "longitud mà xima de la cadena de diferències permesa en el paquet resultant" +#: builtin/pack-objects.c msgid "reuse existing deltas" msgstr "reusa les diferències existents" +#: builtin/pack-objects.c msgid "reuse existing objects" msgstr "reusa els objectes existents" +#: builtin/pack-objects.c msgid "use OFS_DELTA objects" msgstr "usa objectes OFS_DELTA" +#: builtin/pack-objects.c msgid "use threads when searching for best delta matches" msgstr "usa fils en cercar les millors coincidències de diferències" +#: builtin/pack-objects.c msgid "do not create an empty pack output" msgstr "no creïs una emissió de paquet buit" +#: builtin/pack-objects.c msgid "read revision arguments from standard input" msgstr "llegeix els arguments de revisió des de l'entrada està ndard" +#: builtin/pack-objects.c msgid "limit the objects to those that are not yet packed" msgstr "limita els objectes a aquells que encara no estan empaquetats" +#: builtin/pack-objects.c msgid "include objects reachable from any reference" msgstr "inclou els objectes abastables de qualsevol referència" +#: builtin/pack-objects.c msgid "include objects referred by reflog entries" msgstr "" "inclou els objectes als quals facin referència les entrades del registre de " "referències" +#: builtin/pack-objects.c msgid "include objects referred to by the index" msgstr "inclou els objectes als quals faci referència l'Ãndex" +#: builtin/pack-objects.c msgid "read packs from stdin" msgstr "llegeix els paquets des de stdin" +#: builtin/pack-objects.c msgid "output pack to stdout" msgstr "emet el paquet a stdout" +#: builtin/pack-objects.c msgid "include tag objects that refer to objects to be packed" msgstr "" "inclou els objectes d'etiqueta que facin referència als objectes a empaquetar" +#: builtin/pack-objects.c msgid "keep unreachable objects" msgstr "retén els objectes inabastables" +#: builtin/pack-objects.c msgid "pack loose unreachable objects" msgstr "empaqueta els objectes inabastables solts" +#: builtin/pack-objects.c msgid "unpack unreachable objects newer than <time>" msgstr "desempaqueta els objectes inabastables més nous que <data>" +#: builtin/pack-objects.c msgid "create a cruft pack" msgstr "crea un paquet superflu" +#: builtin/pack-objects.c msgid "expire cruft objects older than <time>" msgstr "fes caducar els objectes superflus més antics que <data>" +#: builtin/pack-objects.c msgid "use the sparse reachability algorithm" msgstr "utilitza l'algorisme d'accessibilitat dispers" +#: builtin/pack-objects.c msgid "create thin packs" msgstr "crea paquets prims" +#: builtin/pack-objects.c msgid "create packs suitable for shallow fetches" msgstr "crea paquets adequats per a les obtencions superficials" +#: builtin/pack-objects.c msgid "ignore packs that have companion .keep file" msgstr "ignora els paquets que tinguin un fitxer .keep corresponent" +#: builtin/pack-objects.c msgid "ignore this pack" msgstr "ignora aquest paquet" +#: builtin/pack-objects.c msgid "pack compression level" msgstr "nivell de compressió de paquet" +#: builtin/pack-objects.c msgid "do not hide commits by grafts" msgstr "no amaguis les comissions per empelt" +#: builtin/pack-objects.c msgid "use a bitmap index if available to speed up counting objects" msgstr "" "usa un Ãndex de mapa de bits, si està disponible, per a accelerar el " "recompte d'objectes" +#: builtin/pack-objects.c msgid "write a bitmap index together with the pack index" msgstr "escriu un Ãndex de mapa de bits juntament amb l'Ãndex de paquet" +#: builtin/pack-objects.c msgid "write a bitmap index if possible" msgstr "escriu un Ãndex de mapa de bits si és possible" +#: builtin/pack-objects.c msgid "handling for missing objects" msgstr "gestió dels objectes absents" +#: builtin/pack-objects.c msgid "do not pack objects in promisor packfiles" msgstr "no empaquetis els objectes als fitxers de paquet «promisor»" +#: builtin/pack-objects.c msgid "respect islands during delta compression" msgstr "respecta les illes durant la compressió delta" +#: builtin/pack-objects.c msgid "protocol" msgstr "protocol" +#: builtin/pack-objects.c msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" msgstr "" "exclou qualsevol uploadpack.blobpackfileuri configurat amb aquest protocol" +#: builtin/pack-objects.c #, c-format msgid "delta chain depth %d is too deep, forcing %d" msgstr "la profunditat de la cadena delta %d és massa profunda, forçant %d" +#: builtin/pack-objects.c #, c-format msgid "pack.deltaCacheLimit is too high, forcing %d" msgstr "pack.deltaCacheLimit és massa alt, forçant %d" +#: builtin/pack-objects.c config.c #, c-format msgid "bad pack compression level %d" msgstr "nivell de compressió de paquet %d erroni" +#: builtin/pack-objects.c msgid "--max-pack-size cannot be used to build a pack for transfer" msgstr "" "--max-pack-size no es pot utilitzar per a construir un paquet per a la " "transferència" +#: builtin/pack-objects.c msgid "minimum pack size limit is 1 MiB" msgstr "el lÃmit mÃnim de mida del paquet és 1 MiB" +#: builtin/pack-objects.c msgid "--thin cannot be used to build an indexable pack" msgstr "--thin no es pot utilitzar per a construir un paquet indexable" +#: builtin/pack-objects.c msgid "cannot use --filter with --stdin-packs" msgstr "no es pot utilitzar --filter sense --stdin-packs" +#: builtin/pack-objects.c msgid "cannot use internal rev list with --stdin-packs" msgstr "no es pot utilitzar la llista de revisió interna amb --stdin-packs" +#: builtin/pack-objects.c msgid "cannot use internal rev list with --cruft" msgstr "no es pot utilitzar la llista de revisió interna amb --cruft" +#: builtin/pack-objects.c msgid "cannot use --stdin-packs with --cruft" msgstr "no es pot --stdin-packs amb --cruft" +#: builtin/pack-objects.c msgid "Enumerating objects" msgstr "S'estan enumerant els objectes" +#: builtin/pack-objects.c #, c-format msgid "" "Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-" @@ -9473,6 +12142,7 @@ msgstr "" "Total %<PRIu32> (%<PRIu32> diferències), reusats %<PRIu32> (%<PRIu32> " "diferències), paquets reusats %<PRIu32> (de %<PRIuMAX>)" +#: builtin/pack-redundant.c msgid "" "'git pack-redundant' is nominated for removal.\n" "If you still use this command, please add an extra\n" @@ -9486,91 +12156,124 @@ msgstr "" "i feu-nos saber que encara l'useu enviant un correu electrònic\n" "a <git@vger.kernel.org>. Grà cies.\n" +#: builtin/pack-redundant.c msgid "refusing to run without --i-still-use-this" msgstr "es rebutja a executar sense --i-still-use-this" +#: builtin/pack-refs.c msgid "" -"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude " +"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude " "<pattern>]" msgstr "" -"git pack-refs [--all] [--no-prune] [--include <patró>] [--exclude <patró>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <patró>] [--exclude " +"<patró>]" +#: builtin/pack-refs.c msgid "pack everything" msgstr "empaqueta-ho tot" +#: builtin/pack-refs.c msgid "prune loose refs (default)" msgstr "poda les referències soltes (per defecte)" +#: builtin/pack-refs.c +msgid "auto-pack refs as needed" +msgstr "auto-empaqueta referències si cal" + +#: builtin/pack-refs.c msgid "references to include" msgstr "referències a incloure" +#: builtin/pack-refs.c msgid "references to exclude" msgstr "referències a excloure" +#: builtin/patch-id.c msgid "git patch-id [--stable | --unstable | --verbatim]" msgstr "git patch-id [--stable | --unstable | --verbatim]" +#: builtin/patch-id.c msgid "use the unstable patch-id algorithm" msgstr "utilitza l'algorisme inestable de patch-id" +#: builtin/patch-id.c msgid "use the stable patch-id algorithm" msgstr "utilitza l'algorisme estable de patch-id" +#: builtin/patch-id.c msgid "don't strip whitespace from the patch" msgstr "no eliminis els espais en blanc del pedaç" +#: builtin/prune.c msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]" -msgstr "git prune [-n] [-v] [--progress] [--expire <data>] [--] [<head>...]" +msgstr "git prune [-n] [-v] [--progress] [--expire <data>] [--] [<cap>...]" +#: builtin/prune.c msgid "report pruned objects" msgstr "informa d'objectes podats" +#: builtin/prune.c msgid "expire objects older than <time>" msgstr "fes caducar els objectes més antics que <data>" +#: builtin/prune.c msgid "limit traversal to objects outside promisor packfiles" msgstr "" "limita el recorregut als objectes fora dels fitxers de paquet «promisor»" +#: builtin/prune.c msgid "cannot prune in a precious-objects repo" msgstr "no es pot podar en un repositori d'objectes preciosos" +#: builtin/pull.c msgid "git pull [<options>] [<repository> [<refspec>...]]" -msgstr "git pull [<opcions>] [<repositori> [<especificació-de-referència>...]]" +msgstr "git pull [<opcions>] [<repositori> [<especificació-referència>...]]" +#: builtin/pull.c msgid "control for recursive fetching of submodules" msgstr "controla l'obtenció recursiva de submòduls" +#: builtin/pull.c msgid "Options related to merging" msgstr "Opcions relacionades amb fusionar" +#: builtin/pull.c msgid "incorporate changes by rebasing rather than merging" msgstr "incorpora els canvis fent «rebase» en lloc de fusionar" +#: builtin/pull.c builtin/revert.c msgid "allow fast-forward" msgstr "permet l'avanç rà pid" +#: builtin/pull.c msgid "control use of pre-merge-commit and commit-msg hooks" msgstr "controla l'ús dels lligams pre-merge-commit i commit-msg" +#: builtin/pull.c parse-options.h msgid "automatically stash/stash pop before and after" msgstr "fes «stash» i «stash pop» automà ticament abans i després" +#: builtin/pull.c msgid "Options related to fetching" msgstr "Opcions relacionades amb obtenir" +#: builtin/pull.c msgid "force overwrite of local branch" msgstr "força la sobreescriptura de la branca local" +#: builtin/pull.c msgid "number of submodules pulled in parallel" msgstr "nombre de submòduls baixats en paral·lel" +#: builtin/pull.c parse-options.h msgid "use IPv4 addresses only" msgstr "usa només adreces IPv4" +#: builtin/pull.c parse-options.h msgid "use IPv6 addresses only" msgstr "usa només adreces IPv6" +#: builtin/pull.c msgid "" "There is no candidate for rebasing against among the refs that you just " "fetched." @@ -9578,11 +12281,13 @@ msgstr "" "No hi ha cap candidat sobre el qual fer «rebase» entre les referències que " "acabeu d'obtenir." +#: builtin/pull.c msgid "" "There are no candidates for merging among the refs that you just fetched." msgstr "" "No hi ha candidats per a fusionar entre les referències que acabeu d'obtenir." +#: builtin/pull.c msgid "" "Generally this means that you provided a wildcard refspec which had no\n" "matches on the remote end." @@ -9590,6 +12295,7 @@ msgstr "" "Generalment això vol dir que heu proveït una especificació de\n" "referència de comodà que no tenia cap coincidència en el costat remot." +#: builtin/pull.c #, c-format msgid "" "You asked to pull from the remote '%s', but did not specify\n" @@ -9600,33 +12306,42 @@ msgstr "" "Perquè aquest no és el remot configurat per defecte per a la vostra\n" "branca actual, heu d'especificar una branca en la lÃnia d'ordres." +#: builtin/pull.c builtin/rebase.c msgid "You are not currently on a branch." msgstr "Actualment no sou en cap branca." +#: builtin/pull.c msgid "Please specify which branch you want to rebase against." msgstr "Especifiqueu sobre quina branca voleu fer «rebase»." +#: builtin/pull.c msgid "Please specify which branch you want to merge with." msgstr "Especifiqueu amb quina branca voleu fusionar." +#: builtin/pull.c msgid "See git-pull(1) for details." msgstr "Vegeu git-pull(1) per a més informació." +#: builtin/pull.c builtin/rebase.c msgid "<remote>" msgstr "<remot>" +#: builtin/pull.c scalar.c msgid "<branch>" msgstr "<branca>" +#: builtin/pull.c builtin/rebase.c msgid "There is no tracking information for the current branch." msgstr "No hi ha cap informació de seguiment per a la branca actual." +#: builtin/pull.c msgid "" "If you wish to set tracking information for this branch you can do so with:" msgstr "" "Si voleu establir la informació de seguiment per a aquesta branca, podeu fer-" "ho amb:" +#: builtin/pull.c #, c-format msgid "" "Your configuration specifies to merge with the ref '%s'\n" @@ -9635,13 +12350,16 @@ msgstr "" "La vostra configuració especifica fusionar amb la referència «%s»\n" "del remot, però no s'ha obtingut tal referència." +#: builtin/pull.c #, c-format msgid "unable to access commit %s" msgstr "no s'ha pogut accedir a la comissió %s" +#: builtin/pull.c msgid "ignoring --verify-signatures for rebase" msgstr "s'està ignorant --verify-signatures en fer «rebase»" +#: builtin/pull.c msgid "" "You have divergent branches and need to specify how to reconcile them.\n" "You can do so by running one of the following commands sometime before\n" @@ -9671,26 +12389,31 @@ msgstr "" "--no-rebase o --ff-only en la lÃnia d'ordres per a sobreescriure el valor\n" "per defecte de la configuració en aquesta execució.\n" +#: builtin/pull.c msgid "Updating an unborn branch with changes added to the index." msgstr "" "S'està actualitzant una branca no nascuda amb canvis afegits a l'Ãndex." +#: builtin/pull.c msgid "pull with rebase" msgstr "baixar fent «rebase»" +#: builtin/pull.c builtin/rebase.c msgid "Please commit or stash them." msgstr "Cometeu-los o emmagatzemeu-los." +#: builtin/pull.c #, c-format msgid "" "fetch updated the current branch head.\n" "fast-forwarding your working tree from\n" "commit %s." msgstr "" -"l'obtenció ha actualitzat HEAD de la branca actual.\n" +"l'obtenció ha actualitzat el HEAD de la branca actual.\n" "s'està avançant rà pidament el vostre arbre de treball des de\n" "la comissió %s." +#: builtin/pull.c #, c-format msgid "" "Cannot fast-forward your working tree.\n" @@ -9708,32 +12431,41 @@ msgstr "" "$ git reset --hard\n" "per a recuperar." +#: builtin/pull.c msgid "Cannot merge multiple branches into empty head." msgstr "No es poden fusionar múltiples branques a una HEAD buida." +#: builtin/pull.c msgid "Cannot rebase onto multiple branches." msgstr "No es pot fer «rebase» sobre múltiples branques." +#: builtin/pull.c msgid "Cannot fast-forward to multiple branches." msgstr "No es pot fer un avançament rà pid a branques múltiples." +#: builtin/pull.c msgid "Need to specify how to reconcile divergent branches." msgstr "Cal especificar com reconciliar les branques divergents." +#: builtin/pull.c msgid "cannot rebase with locally recorded submodule modifications" msgstr "" "no es pot fer «rebase» amb modificacions als submòduls enregistrades " "localment" +#: builtin/push.c msgid "git push [<options>] [<repository> [<refspec>...]]" -msgstr "git push [<opcions>] [<repositori> [<especificació-de-referència>...]]" +msgstr "git push [<opcions>] [<repositori> [<especificació-referència>...]]" +#: builtin/push.c msgid "tag shorthand without <tag>" -msgstr "abreviatura d'etiqueta sense <tag>" +msgstr "abreviatura d'etiqueta sense <etiqueta>" +#: builtin/push.c msgid "--delete only accepts plain target ref names" msgstr "--delete només accepta noms de referència de destà senzills" +#: builtin/push.c msgid "" "\n" "To choose either option permanently, see push.default in 'git help config'.\n" @@ -9742,6 +12474,7 @@ msgstr "" "Per a triar qualsevol de les opcions permanentment, vegeu push.default a " "«git help config».\n" +#: builtin/push.c msgid "" "\n" "To avoid automatically configuring an upstream branch when its name\n" @@ -9753,6 +12486,7 @@ msgstr "" "no coincideix amb el de la branca local, vegeu l'opció «simple» de\n" "«branch.autoSetupMerge» a «git help config».\n" +#: builtin/push.c #, c-format msgid "" "The upstream branch of your current branch does not match\n" @@ -9777,6 +12511,7 @@ msgstr "" " git push %s HEAD\n" "%s%s" +#: builtin/push.c #, c-format msgid "" "You are not currently on a branch.\n" @@ -9791,6 +12526,7 @@ msgstr "" "\n" " git push %s HEAD:<nom-de-branca-remota>\n" +#: builtin/push.c msgid "" "\n" "To have this happen automatically for branches without a tracking\n" @@ -9801,6 +12537,7 @@ msgstr "" "seguiment\n" "font, vegeu «push.autoSetupRemote» a «git help config».\n" +#: builtin/push.c #, c-format msgid "" "The current branch %s has no upstream branch.\n" @@ -9815,17 +12552,20 @@ msgstr "" " git push --set-upstream %s %s\n" "%s" +#: builtin/push.c #, c-format msgid "The current branch %s has multiple upstream branches, refusing to push." msgstr "" "La branca actual %s té múltiples branques fonts, s'està refusant pujar." +#: builtin/push.c msgid "" "You didn't specify any refspecs to push, and push.default is \"nothing\"." msgstr "" "No heu especificat cap especificació de referència a pujar, i push.default " "és «nothing»." +#: builtin/push.c #, c-format msgid "" "You are pushing to remote '%s', which is not the upstream of\n" @@ -9836,6 +12576,7 @@ msgstr "" "branca actual «%s», sense dir-me què pujar per a actualitzar\n" "quina branca remota." +#: builtin/push.c msgid "" "Updates were rejected because the tip of your current branch is behind\n" "its remote counterpart. If you want to integrate the remote changes,\n" @@ -9847,6 +12588,7 @@ msgstr "" "remots useu «git pull» abans de tornar a pujar.\n" "Vegeu «Note about fast-forwards» a «git push --help» per a més detalls." +#: builtin/push.c msgid "" "Updates were rejected because a pushed branch tip is behind its remote\n" "counterpart. If you want to integrate the remote changes, use 'git pull'\n" @@ -9858,6 +12600,7 @@ msgstr "" "utilitzeu «git pull» abans de tornar a pujar.\n" "Vegeu «Note about fast-forwards» a «git push --help» per a més detalls." +#: builtin/push.c msgid "" "Updates were rejected because the remote contains work that you do not\n" "have locally. This is usually caused by another repository pushing to\n" @@ -9867,15 +12610,17 @@ msgid "" msgstr "" "Les actualitzacions s'han rebutjat perquè el remot conté canvis que no " "teniu\n" -"localment. Això sol ser causat per un altre repositori que a pujat a\n" +"localment. Això sol ser causat per un altre repositori que ha pujat a\n" "la mateixa referència. Si voleu integrar els canvis remots, utilitzeu\n" "«git pull» abans de tornar a pujar.\n" "Vegeu «Note about fast-forwards» a «git push --help» per a més detalls." +#: builtin/push.c msgid "Updates were rejected because the tag already exists in the remote." msgstr "" "S'han rebutjat les actualitzacions perquè l'etiqueta ja existeix en el remot." +#: builtin/push.c msgid "" "You cannot update a remote ref that points at a non-commit object,\n" "or update a remote ref to make it point at a non-commit object,\n" @@ -9886,6 +12631,7 @@ msgstr "" "a fer que assenyali un objecte no de comissió, sense usar l'opció\n" "«--force».\n" +#: builtin/push.c msgid "" "Updates were rejected because the tip of the remote-tracking branch has\n" "been updated since the last checkout. If you want to integrate the\n" @@ -9897,14 +12643,17 @@ msgstr "" "canvis remots, utilitzeu «git pull» abans de tornar a pujar.\n" "Vegeu «Note about fast-forwards» a «git push --help» per a més detalls." +#: builtin/push.c #, c-format msgid "Pushing to %s\n" msgstr "S'està pujant a %s\n" +#: builtin/push.c #, c-format msgid "failed to push some refs to '%s'" msgstr "s'ha produït un error en pujar algunes referències a «%s»" +#: builtin/push.c msgid "" "recursing into submodule with push.recurseSubmodules=only; using on-demand " "instead" @@ -9912,71 +12661,93 @@ msgstr "" "cerca recursivament en el submòdul amb push.recurseSubmodules=only; " "utilitzant «on-demand» en el seu lloc" +#: builtin/push.c builtin/send-pack.c submodule-config.c #, c-format msgid "invalid value for '%s'" msgstr "valor no và lid per a «%s»" +#: builtin/push.c builtin/submodule--helper.c msgid "repository" msgstr "repositori" +#: builtin/push.c msgid "push all branches" msgstr "puja totes les referències" +#: builtin/push.c builtin/send-pack.c msgid "mirror all refs" msgstr "reflecteix totes les referències" +#: builtin/push.c msgid "delete refs" msgstr "suprimeix les referències" +#: builtin/push.c msgid "push tags (can't be used with --all or --branches or --mirror)" msgstr "puja les etiquetes (no es pot usar amb --all, --branches o --mirror)" +#: builtin/push.c builtin/send-pack.c msgid "force updates" msgstr "força les actualitzacions" +#: builtin/push.c builtin/send-pack.c msgid "<refname>:<expect>" -msgstr "<nom-de-referència>:<esperat>" +msgstr "<nom-referència>:<esperat>" +#: builtin/push.c builtin/send-pack.c msgid "require old value of ref to be at this value" msgstr "requereix que el valor antic de la referència sigui d'aquest valor" +#: builtin/push.c builtin/send-pack.c msgid "require remote updates to be integrated locally" msgstr "requereix que les actualitzacions remotes s'integrin localment" +#: builtin/push.c msgid "control recursive pushing of submodules" msgstr "controla la pujada recursiva dels submòduls" +#: builtin/push.c builtin/send-pack.c msgid "use thin pack" msgstr "usa el paquet prim" +#: builtin/push.c builtin/send-pack.c msgid "receive pack program" msgstr "programa que rep els paquets" +#: builtin/push.c msgid "set upstream for git pull/status" msgstr "estableix la font per a git pull/status" +#: builtin/push.c msgid "prune locally removed refs" msgstr "poda les referències eliminades localment" +#: builtin/push.c msgid "bypass pre-push hook" msgstr "evita el lligam de prepujada" +#: builtin/push.c msgid "push missing but relevant tags" msgstr "puja les etiquetes absents però rellevants" +#: builtin/push.c builtin/send-pack.c msgid "GPG sign the push" msgstr "signa la pujada amb GPG" +#: builtin/push.c builtin/send-pack.c msgid "request atomic transaction on remote side" msgstr "demana una transacció atòmica al costat remot" +#: builtin/push.c msgid "--delete doesn't make sense without any refs" msgstr "--delete no té sentit sense referències" +#: builtin/push.c t/helper/test-bundle-uri.c #, c-format msgid "bad repository '%s'" msgstr "repositori incorrecte «%s»" +#: builtin/push.c msgid "" "No configured push destination.\n" "Either specify the URL from the command-line or configure a remote " @@ -9998,54 +12769,70 @@ msgstr "" "\n" " git push <nom>\n" +#: builtin/push.c msgid "--all can't be combined with refspecs" msgstr "--all no es pot combinar amb especificacions de referència" +#: builtin/push.c msgid "--mirror can't be combined with refspecs" msgstr "--mirror no es pot combinar amb especificacions de referència" +#: builtin/push.c msgid "push options must not have new line characters" msgstr "les opcions de pujada no han de tenir carà cters de lÃnia nova" +#: builtin/range-diff.c msgid "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>" msgstr "git range-diff [<opcions>] <old-base>..<old-tip> <new-base>..<new-tip>" +#: builtin/range-diff.c msgid "git range-diff [<options>] <old-tip>...<new-tip>" msgstr "git range-diff [<opcions>] <old-tip>...<new-tip>" +#: builtin/range-diff.c msgid "git range-diff [<options>] <base> <old-tip> <new-tip>" msgstr "git range-diff [<opcions>] <base> <old-tip> <new-tip>" +#: builtin/range-diff.c msgid "use simple diff colors" msgstr "utilitza colors simples de diff" +#: builtin/range-diff.c msgid "notes" msgstr "notes" +#: builtin/range-diff.c msgid "passed to 'git log'" msgstr "passa-ho a «git log»" +#: builtin/range-diff.c msgid "only emit output related to the first range" msgstr "emet només la sortida relacionada amb el primer interval" +#: builtin/range-diff.c msgid "only emit output related to the second range" msgstr "emet només la sortida relacionada amb el segon interval" +#: builtin/range-diff.c #, c-format msgid "not a revision: '%s'" msgstr "«%s» no és una revisió" +#: builtin/range-diff.c #, c-format msgid "not a commit range: '%s'" msgstr "no és un rang de comissions: «%s»" +#: builtin/range-diff.c #, c-format msgid "not a symmetric range: '%s'" msgstr "no és un rang simètric: «%s»" +#: builtin/range-diff.c msgid "need two commit ranges" msgstr "calen dos rangs de comissió" +#: builtin/read-tree.c msgid "" "git read-tree [(-m [--trivial] [--aggressive] | --reset | --" "prefix=<prefix>)\n" @@ -10057,60 +12844,79 @@ msgstr "" " [-u | -i]] [--index-output=<fitxer>] [--no-sparse-checkout]\n" " (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])" +#: builtin/read-tree.c msgid "write resulting index to <file>" msgstr "escriu l'Ãndex resultant al <fitxer>" +#: builtin/read-tree.c msgid "only empty the index" msgstr "només buida l'Ãndex" +#: builtin/read-tree.c msgid "Merging" msgstr "S'està fusionant" +#: builtin/read-tree.c msgid "perform a merge in addition to a read" msgstr "realitza una fusió a més d'una lectura" +#: builtin/read-tree.c msgid "3-way merge if no file level merging required" msgstr "fusió de 3 vies si no cal fusió a nivell de fitxers" +#: builtin/read-tree.c msgid "3-way merge in presence of adds and removes" msgstr "fusió de 3 vies en presència d'afegiments i eliminacions" +#: builtin/read-tree.c msgid "same as -m, but discard unmerged entries" msgstr "el mateix que -m, però descarta les entrades no fusionades" +#: builtin/read-tree.c msgid "<subdirectory>/" msgstr "<subdirectori>/" +#: builtin/read-tree.c msgid "read the tree into the index under <subdirectory>/" msgstr "llegeix l'arbre a l'Ãndex sota <subdirectori>/" +#: builtin/read-tree.c msgid "update working tree with merge result" msgstr "actualitza l'arbre de treball amb el resultat de fusió" +#: builtin/read-tree.c msgid "gitignore" msgstr "gitignore" +#: builtin/read-tree.c msgid "allow explicitly ignored files to be overwritten" msgstr "permet que els fitxers explÃcitament ignorats se sobreescriguin" +#: builtin/read-tree.c msgid "don't check the working tree after merging" msgstr "no comprovis l'arbre de treball després de fusionar" +#: builtin/read-tree.c msgid "don't update the index or the work tree" msgstr "no actualitzis l'Ãndex ni l'arbre de treball" +#: builtin/read-tree.c msgid "skip applying sparse checkout filter" msgstr "omet l'aplicació del filtre d'agafament parcial" +#: builtin/read-tree.c msgid "debug unpack-trees" msgstr "depura unpack-trees" +#: builtin/read-tree.c msgid "suppress feedback messages" msgstr "suprimeix els missatges de retroacció" +#: builtin/read-tree.c msgid "You need to resolve your current index first" msgstr "Primer heu de resoldre el vostre Ãndex actual" +#: builtin/rebase.c msgid "" "git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] " "[<upstream> [<branch>]]" @@ -10118,64 +12924,61 @@ msgstr "" "git rebase [-i] [options] [--exec <ordre>] [--onto <newbase> | --keep-base] " "[<upstream> [<branca>]]" +#: builtin/rebase.c msgid "" "git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]" msgstr "" "git rebase [-i] [options] [--exec <ordre>] [--onto <newbase>] --root " "[<branca>]" +#: builtin/rebase.c sequencer.c #, c-format msgid "could not read '%s'." msgstr "no s'ha pogut llegir «%s»." +#: builtin/rebase.c #, c-format msgid "could not create temporary %s" msgstr "no s'ha pogut crear el fitxer temporal %s" +#: builtin/rebase.c msgid "could not mark as interactive" msgstr "no s'ha pogut marcar com a interactiu" +#: builtin/rebase.c msgid "could not generate todo list" msgstr "no s'ha pogut generar la llista per a fer" +#: builtin/rebase.c msgid "a base commit must be provided with --upstream or --onto" msgstr "s'ha de proporcionar una comissió base amb --upstream o --onto" +#: builtin/rebase.c #, c-format msgid "%s requires the merge backend" msgstr "%s requereix un rerefons de fusió" +#: builtin/rebase.c #, c-format msgid "invalid onto: '%s'" msgstr "no và lid a: «%s»" +#: builtin/rebase.c #, c-format msgid "invalid orig-head: '%s'" msgstr "orig-head no és và lid: «%s»" +#: builtin/rebase.c #, c-format msgid "ignoring invalid allow_rerere_autoupdate: '%s'" msgstr "s'ignora allow_rerere_autoupdate no và lid: «%s»" +#: builtin/rebase.c builtin/rm.c sequencer.c #, c-format msgid "could not remove '%s'" msgstr "no s'ha pogut eliminar «%s»" -msgid "" -"Resolve all conflicts manually, mark them as resolved with\n" -"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n" -"You can instead skip this commit: run \"git rebase --skip\".\n" -"To abort and get back to the state before \"git rebase\", run \"git rebase --" -"abort\"." -msgstr "" -"Resoleu tots els conflictes manualment, marqueu-los com a resolts amb\n" -"«git add/rm <fitxers_amb_conflicte>», llavors executeu «git rebase --" -"continue».\n" -"Alternativament podeu ometre aquesta comissió: executeu «git rebase --" -"skip».\n" -"Per a avortar i tornar a l'estat anterior abans de l'ordre «git rebase», " -"executeu «git rebase --abort»." - +#: builtin/rebase.c #, c-format msgid "" "\n" @@ -10194,24 +12997,34 @@ msgstr "" "\n" "Com a resultat, git no pot fer un «rebase» d'elles." +#: builtin/rebase.c #, c-format msgid "Unknown rebase-merges mode: %s" msgstr "Mode de fusió de rebase desconegut: %s" +#: builtin/rebase.c #, c-format msgid "could not switch to %s" msgstr "no s'ha pogut commutar a %s" +#: builtin/rebase.c msgid "apply options and merge options cannot be used together" msgstr "les opcions apply i merge no es poden usar juntes" +#: builtin/rebase.c +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask és obslolet; utilitzeu '--empty=stop' en el seu lloc." + +#: builtin/rebase.c #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" -"tipus buit no reconegut «%s»; els valors và lids són «drop», «keep» i «ask»." +"tipus buit «%s» no reconegut; els valors và lids són \"drop\", \"keep\" i " +"\"stop\"." +#: builtin/rebase.c msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " "working in a future version of Git. Use --rebase-merges without an argument " @@ -10221,6 +13034,7 @@ msgstr "" "funcionar en una versió futura del Git. Utilitzeu --rebase-merges sense un " "argument, que fa el mateix." +#: builtin/rebase.c #, c-format msgid "" "%s\n" @@ -10237,6 +13051,7 @@ msgstr "" " git rebase '<branca>'\n" "\n" +#: builtin/rebase.c #, c-format msgid "" "If you wish to set tracking information for this branch you can do so with:\n" @@ -10250,128 +13065,169 @@ msgstr "" " git branch --set-upstream-to=%s/<branca> %s\n" "\n" +#: builtin/rebase.c msgid "exec commands cannot contain newlines" msgstr "les ordres exec no poden contenir lÃnies noves" +#: builtin/rebase.c msgid "empty exec command" msgstr "ordre exec buida" +#: builtin/rebase.c msgid "rebase onto given branch instead of upstream" msgstr "fes un «rebase» en la branca donada en comptes de la font" +#: builtin/rebase.c msgid "use the merge-base of upstream and branch as the current base" msgstr "utilitza la base de fusió de la font i la branca com a base actual" +#: builtin/rebase.c msgid "allow pre-rebase hook to run" msgstr "permet al lligam pre-rebase executar-se" +#: builtin/rebase.c msgid "be quiet. implies --no-stat" msgstr "silenciós. Implica --no-stat" +#: builtin/rebase.c msgid "display a diffstat of what changed upstream" msgstr "mostra un «diffstat» del que ha canviat a la font" +#: builtin/rebase.c msgid "do not show diffstat of what changed upstream" msgstr "no mostris «diffstat» del que ha canviat a la font" +#: builtin/rebase.c msgid "add a Signed-off-by trailer to each commit" msgstr "afegeix un «trailer» tipus «Signed-off-by» a cada comissió" +#: builtin/rebase.c msgid "make committer date match author date" msgstr "fes que la data del «committer» coincideixi amb la data de l'autor" +#: builtin/rebase.c msgid "ignore author date and use current date" msgstr "ignora la data de l'autor i utilitza la data actual" +#: builtin/rebase.c msgid "synonym of --reset-author-date" msgstr "sinònim de --reset-author-date" +#: builtin/rebase.c msgid "passed to 'git apply'" msgstr "passa-ho a «git apply»" +#: builtin/rebase.c msgid "ignore changes in whitespace" msgstr "ignora els canvis d'espais en blanc" +#: builtin/rebase.c msgid "cherry-pick all commits, even if unchanged" msgstr "«cherry pick» totes les comissions, inclús les no canviades" +#: builtin/rebase.c msgid "continue" msgstr "continua" +#: builtin/rebase.c msgid "skip current patch and continue" msgstr "omet el pedaç actual i continua" +#: builtin/rebase.c msgid "abort and check out the original branch" msgstr "interromp i agafa la branca original" +#: builtin/rebase.c msgid "abort but keep HEAD where it is" msgstr "interromp però manté HEAD on és" +#: builtin/rebase.c msgid "edit the todo list during an interactive rebase" msgstr "edita la llista de coses a fer durant un «rebase» interactiu" +#: builtin/rebase.c msgid "show the patch file being applied or merged" msgstr "mostra el pedaç que s'està aplicant o fusionant" +#: builtin/rebase.c msgid "use apply strategies to rebase" msgstr "utilitza estratègies d'aplicació per a fer «rebase»" +#: builtin/rebase.c msgid "use merging strategies to rebase" msgstr "utilitza estratègies de fusió per a fer «rebase»" +#: builtin/rebase.c msgid "let the user edit the list of commits to rebase" msgstr "permet a l'usuari editar la llista de comissions a fer «rebase»" +#: builtin/rebase.c msgid "(REMOVED) was: try to recreate merges instead of ignoring them" msgstr "(SUPRIMIT) era: intenta recrear fusions en lloc d'ignorar-les" +#: builtin/rebase.c builtin/revert.c msgid "how to handle commits that become empty" msgstr "com gestionar les comissions que queden buides" +#: builtin/rebase.c msgid "keep commits which start empty" msgstr "manté les comissions que comencen en blanc" +#: builtin/rebase.c msgid "move commits that begin with squash!/fixup! under -i" msgstr "mou les comissions que comencen amb squash!/fixup! sota -i" +#: builtin/rebase.c msgid "update branches that point to commits that are being rebased" msgstr "" "actualitza les branques que apunten a comissions a les quals se'ls està fent " "«rebase»" +#: builtin/rebase.c msgid "add exec lines after each commit of the editable list" msgstr "afegeix lÃnies d'exec després de cada comissió de la llista editable" +#: builtin/rebase.c msgid "allow rebasing commits with empty messages" msgstr "permet fer «rebase» de les comissions amb missatges buits" +#: builtin/rebase.c msgid "try to rebase merges instead of skipping them" msgstr "intenta fer «rebase» de les fusions en comptes d'ometre-les" +#: builtin/rebase.c msgid "use 'merge-base --fork-point' to refine upstream" msgstr "usa «merge-base --fork-point» per a refinar la font" +#: builtin/rebase.c msgid "use the given merge strategy" msgstr "utilitza l'estratègia de fusió donada" +#: builtin/rebase.c builtin/revert.c msgid "option" msgstr "opció" +#: builtin/rebase.c msgid "pass the argument through to the merge strategy" msgstr "passa l'argument a l'estratègia de fusió" +#: builtin/rebase.c msgid "rebase all reachable commits up to the root(s)" msgstr "fes «rebase» de totes les comissions accessibles fins a l'arrel" +#: builtin/rebase.c msgid "automatically re-schedule any `exec` that fails" msgstr "torna a planificar automà ticament qualsevol «exec» que falli" +#: builtin/rebase.c msgid "apply all changes, even those already present upstream" msgstr "aplica tots els canvis, fins i tot els que ja estan a la font" +#: builtin/rebase.c msgid "It looks like 'git am' is in progress. Cannot rebase." msgstr "Sembla que «git am» està en curs. No es pot fer «rebase»." +#: builtin/rebase.c msgid "" "`rebase --preserve-merges` (-p) is no longer supported.\n" "Use `git rebase --abort` to terminate current rebase.\n" @@ -10381,6 +13237,7 @@ msgstr "" "Utilitzeu «git rebase --abort» per a finalitzar el «rebase» actual.\n" "O bé baixeu a la versió v2.33, o anterior, per a completar el «rebase»." +#: builtin/rebase.c msgid "" "--preserve-merges was replaced by --rebase-merges\n" "Note: Your `pull.rebase` configuration may also be set to 'preserve',\n" @@ -10390,15 +13247,19 @@ msgstr "" "Nota: la configuració «pull.rebase» també podria estar establerta a\n" "+-«preserve», que ja no s'admet; utilitzeu «merge» en el seu lloc" -msgid "No rebase in progress?" -msgstr "No hi ha un «rebase» en curs?" +#: builtin/rebase.c +msgid "no rebase in progress" +msgstr "no hi ha cap «rebase» en curs" +#: builtin/rebase.c msgid "The --edit-todo action can only be used during interactive rebase." msgstr "L'acció --edit-todo només es pot usar durant un «rebase» interactiu." +#: builtin/rebase.c msgid "Cannot read HEAD" msgstr "No es pot llegir HEAD" +#: builtin/rebase.c msgid "" "You must edit all merge conflicts and then\n" "mark them as resolved using git add" @@ -10406,13 +13267,16 @@ msgstr "" "Heu d'editar tots els conflictes de fusió i després\n" "marcar-los com a resolts fent servir git add" +#: builtin/rebase.c msgid "could not discard worktree changes" msgstr "no s'han pogut descartar els canvis de l'arbre de treball" +#: builtin/rebase.c #, c-format msgid "could not move back to %s" msgstr "no s'ha pogut tornar a %s" +#: builtin/rebase.c #, c-format msgid "" "It seems that there is already a %s directory, and\n" @@ -10432,9 +13296,11 @@ msgstr "" "i després executeu aquesta ordre de nou. S'atura l'operació en cas que\n" "tingueu quelcom valuós.\n" +#: builtin/rebase.c msgid "switch `C' expects a numerical value" msgstr "«switch» «c» espera un valor numèric" +#: builtin/rebase.c msgid "" "apply options are incompatible with rebase.rebaseMerges. Consider adding --" "no-rebase-merges" @@ -10442,6 +13308,7 @@ msgstr "" "les opcions «apply» són incompatibles amb rebase.rebaseMerges. Considereu " "afegir-hi --no-rebase-merges" +#: builtin/rebase.c msgid "" "apply options are incompatible with rebase.updateRefs. Consider adding --no-" "update-refs" @@ -10449,84 +13316,106 @@ msgstr "" "les opcions «apply» són incompatibles amb rebase.updateRefs. Considereu " "afegir-hi --no-update-refs" +#: builtin/rebase.c #, c-format msgid "Unknown rebase backend: %s" msgstr "Rerefons de «rebase» desconegut: %s" +#: builtin/rebase.c msgid "--reschedule-failed-exec requires --exec or --interactive" msgstr "--reschedule-failed-exec requereix --exec o --interactive" +#: builtin/rebase.c #, c-format msgid "invalid upstream '%s'" msgstr "font no và lida: «%s»" +#: builtin/rebase.c msgid "Could not create new root commit" msgstr "No s'ha pogut crear una comissió arrel nova" +#: builtin/rebase.c #, c-format msgid "no such branch/commit '%s'" msgstr "no existeix aquesta branca o comissió «%s»" +#: builtin/rebase.c builtin/submodule--helper.c #, c-format msgid "No such ref: %s" msgstr "No hi ha tal referència: %s" +#: builtin/rebase.c msgid "Could not resolve HEAD to a commit" msgstr "No s'ha pogut resoldre HEAD com a una comissió" +#: builtin/rebase.c #, c-format msgid "'%s': need exactly one merge base with branch" msgstr "«%s»: necessita exactament una base de fusió amb branca" +#: builtin/rebase.c #, c-format msgid "'%s': need exactly one merge base" msgstr "«%s»: necessita exactament una base de fusió" +#: builtin/rebase.c #, c-format msgid "Does not point to a valid commit '%s'" msgstr "No apunta a una comissió và lida «%s»" +#: builtin/rebase.c msgid "HEAD is up to date." msgstr "HEAD està al dia." +#: builtin/rebase.c #, c-format msgid "Current branch %s is up to date.\n" msgstr "La branca actual %s està al dia.\n" +#: builtin/rebase.c msgid "HEAD is up to date, rebase forced." msgstr "La branca actual està al dia, «rebase» forçat." +#: builtin/rebase.c #, c-format msgid "Current branch %s is up to date, rebase forced.\n" msgstr "La branca actual %s està al dia; «rebase» forçat.\n" +#: builtin/rebase.c msgid "The pre-rebase hook refused to rebase." msgstr "El lligam pre-rebase ha refusat a fer «rebase»." +#: builtin/rebase.c #, c-format msgid "Changes to %s:\n" msgstr "Canvis a %s:\n" +#: builtin/rebase.c #, c-format msgid "Changes from %s to %s:\n" msgstr "Canvis de %s a %s:\n" +#: builtin/rebase.c #, c-format msgid "First, rewinding head to replay your work on top of it...\n" msgstr "" "Primer, s'està rebobinant HEAD per a reproduir el vostre treball al " "damunt...\n" +#: builtin/rebase.c msgid "Could not detach HEAD" msgstr "No s'ha pogut separar HEAD" +#: builtin/rebase.c #, c-format msgid "Fast-forwarded %s to %s.\n" msgstr "Avanç rà pid %s a %s.\n" +#: builtin/receive-pack.c msgid "git receive-pack <git-dir>" msgstr "git receive-pack <git-dir>" +#: builtin/receive-pack.c msgid "" "By default, updating the current branch in a non-bare repository\n" "is denied, because it will make the index and work tree inconsistent\n" @@ -10557,6 +13446,7 @@ msgstr "" "per defecte, establiu la variable de configuració\n" "«receive.denyCurrentBranch» a «refuse»." +#: builtin/receive-pack.c msgid "" "By default, deleting the current branch is denied, because the next\n" "'git clone' won't result in any file checked out, causing confusion.\n" @@ -10578,15 +13468,23 @@ msgstr "" "\n" "Per a silenciar aquest missatge, podeu establir-la a «refuse»." +#: builtin/receive-pack.c msgid "quiet" msgstr "silenciós" +#: builtin/receive-pack.c msgid "you must specify a directory" msgstr "heu d'especificar un directori" +#: builtin/reflog.c msgid "git reflog [show] [<log-options>] [<ref>]" -msgstr "git reflog [show] [<log-options>] [<ref>]" +msgstr "git reflog [show] [<opcions-registre>] [<referència>]" + +#: builtin/reflog.c +msgid "git reflog list" +msgstr "git reflog list" +#: builtin/reflog.c msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10598,39 +13496,57 @@ msgstr "" " [--dry-run | -n] [--verbose] [--all [--single-worktree] | " "<refs>...]" +#: builtin/reflog.c msgid "" "git reflog delete [--rewrite] [--updateref]\n" " [--dry-run | -n] [--verbose] <ref>@{<specifier>}..." msgstr "" "git reflog delete [--rewrite] [--updateref]\n" -" [--dry-run | -n] [--verbose] <ref>@{<specifier>}..." +" [--dry-run | -n] [--verbose] " +"<referència>@{<especificador>}..." +#: builtin/reflog.c msgid "git reflog exists <ref>" msgstr "git reflog exists <referència>" +#: builtin/reflog.c #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "marca de temps «%s» donada a «--%s» no és và lida" +#: builtin/reflog.c sequencer.c +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s no accepta arguments: «%s»" + +#: builtin/reflog.c msgid "do not actually prune any entries" msgstr "no eliminis cap entrada" +#: builtin/reflog.c msgid "" "rewrite the old SHA1 with the new SHA1 of the entry that now precedes it" msgstr "reescriu l'antic SHA1 amb el nou SHA1 de l'entrada que ara precedeix" +#: builtin/reflog.c msgid "update the reference to the value of the top reflog entry" -msgstr "actualitza la referència al valor de l'entrada de reflog superior" +msgstr "" +"actualitza la referència al valor de l'entrada de registre de referència " +"superior" +#: builtin/reflog.c msgid "print extra information on screen" msgstr "imprimeix informació extra a la pantalla" +#: builtin/reflog.c msgid "timestamp" msgstr "marca de temps" +#: builtin/reflog.c msgid "prune entries older than the specified time" msgstr "poda les entrades més antigues que el temps especificat" +#: builtin/reflog.c msgid "" "prune entries older than <time> that are not reachable from the current tip " "of the branch" @@ -10638,30 +13554,75 @@ msgstr "" "poda les entrades més antigues de <data> que no es poden accedir des de la " "punta actual de la branca" +#: builtin/reflog.c msgid "prune any reflog entries that point to broken commits" -msgstr "poda qualsevol entrada de reflog que apunti a comissions trencades" +msgstr "" +"poda qualsevol entrada del registre de referències que apunti a comissions " +"trencades" +#: builtin/reflog.c msgid "process the reflogs of all references" -msgstr "processa els reflogs de totes les referències" +msgstr "processa els registres de referències de totes les referències" +#: builtin/reflog.c msgid "limits processing to reflogs from the current worktree only" -msgstr "limita el processament a reflogs només de l'arbre de treball actual" +msgstr "" +"limita el processament només a registres de referències de l'arbre de " +"treball actual" +#: builtin/reflog.c #, c-format msgid "Marking reachable objects..." msgstr "S'estan marcant els objectes abastables..." +#: builtin/reflog.c #, c-format msgid "%s points nowhere!" msgstr "%s no apunta a enlloc" +#: builtin/reflog.c msgid "no reflog specified to delete" -msgstr "no s'ha especificat cap registre de referència per a suprimir" +msgstr "no s'ha especificat cap registre de referències per a suprimir" +#: builtin/reflog.c #, c-format msgid "invalid ref format: %s" msgstr "format de referència no và lid: %s" +#: builtin/refs.c +msgid "git refs migrate --ref-format=<format> [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--dry-run]" + +#: builtin/refs.c +msgid "git refs verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +#: builtin/refs.c +msgid "specify the reference format to convert to" +msgstr "especifiqueu el format de referència al qual voleu convertir" + +#: builtin/refs.c +msgid "perform a non-destructive dry-run" +msgstr "fes una prova no destructiva" + +#: builtin/refs.c +msgid "missing --ref-format=<format>" +msgstr "falta --ref-format=<format>" + +#: builtin/refs.c +#, c-format +msgid "repository already uses '%s' format" +msgstr "el repositori ja usa el format «%s»" + +#: builtin/refs.c +msgid "enable strict checking" +msgstr "habilita la comprovació estricta" + +#: builtin/refs.c +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' no accepta arguments" + +#: builtin/remote.c msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -10669,67 +13630,87 @@ msgstr "" "git remote add [-t <branca>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <nom> <url>" +#: builtin/remote.c msgid "git remote rename [--[no-]progress] <old> <new>" -msgstr "git remote rename [--[no-]progress] <old> <new>" +msgstr "git remote rename [--[no-]progress] <vell> <nou>" +#: builtin/remote.c msgid "git remote remove <name>" msgstr "git remote remove <nom>" +#: builtin/remote.c msgid "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)" msgstr "git remote set-head <nom> (-a | --auto | -d | --delete | <branca>)" +#: builtin/remote.c msgid "git remote [-v | --verbose] show [-n] <name>" msgstr "git remote [-v | --verbose] show [-n] <nom>" +#: builtin/remote.c msgid "git remote prune [-n | --dry-run] <name>" msgstr "git remote prune [-n | --dry-run] <nom>" +#: builtin/remote.c msgid "" "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]" msgstr "" "git remote [-v | --verbose] update [-p | --prune] [(<grup> | <remot>)...]" +#: builtin/remote.c msgid "git remote set-branches [--add] <name> <branch>..." msgstr "git remote set-branches [--add] <nom> <branca>..." +#: builtin/remote.c msgid "git remote get-url [--push] [--all] <name>" msgstr "git remote get-url [--push] [--all] <nom>" +#: builtin/remote.c msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]" -msgstr "git remote set-url [--push] <nom> <url-nou> [<url-antic>]" +msgstr "<git remote set-url [--push] <nom> <url-nou> [<url-vell>]" +#: builtin/remote.c msgid "git remote set-url --add <name> <newurl>" msgstr "git remote set-url --add <nom> <url-nou>" +#: builtin/remote.c msgid "git remote set-url --delete <name> <url>" msgstr "git remote set-url --delete <nom> <url>" +#: builtin/remote.c msgid "git remote add [<options>] <name> <url>" msgstr "git remote add [<opcions>] <nom> <url>" +#: builtin/remote.c msgid "git remote set-branches <name> <branch>..." msgstr "git remote set-branches <nom> <branca>..." +#: builtin/remote.c msgid "git remote set-branches --add <name> <branch>..." msgstr "git remote set-branches --add <nom> <branca>..." +#: builtin/remote.c msgid "git remote show [<options>] <name>" msgstr "git remote show [<opcions>] <nom>" +#: builtin/remote.c msgid "git remote prune [<options>] <name>" msgstr "git remote prune [<opcions>] <nom>" +#: builtin/remote.c msgid "git remote update [<options>] [<group> | <remote>]..." msgstr "git remote update [<opcions>] [<grup> | <remot>]..." +#: builtin/remote.c #, c-format msgid "Updating %s" msgstr "S'està actualitzant %s" +#: builtin/remote.c #, c-format msgid "Could not fetch %s" msgstr "No s'ha pogut obtenir %s" +#: builtin/remote.c msgid "" "--mirror is dangerous and deprecated; please\n" "\t use --mirror=fetch or --mirror=push instead" @@ -10738,13 +13719,16 @@ msgstr "" "\t useu --mirror=fetch o\n" "\t --mirror=push en lloc d'això" +#: builtin/remote.c #, c-format -msgid "unknown mirror argument: %s" -msgstr "argument de «mirror» desconegut: %s" +msgid "unknown --mirror argument: %s" +msgstr "argument de «--mirror» desconegut: %s" +#: builtin/remote.c msgid "fetch the remote branches" msgstr "obtén les branques remotes" +#: builtin/remote.c msgid "" "import all tags and associated objects when fetching\n" "or do not fetch any tag at all (--no-tags)" @@ -10752,57 +13736,72 @@ msgstr "" "importa totes les etiquetes i objectes associats en obtenir\n" "o no obtingueu cap etiqueta (--no-tags)" +#: builtin/remote.c msgid "branch(es) to track" msgstr "branques a seguir" +#: builtin/remote.c msgid "master branch" msgstr "branca mestra" +#: builtin/remote.c msgid "set up remote as a mirror to push to or fetch from" msgstr "estableix el remot com a mirall al qual pujar o del qual obtenir" +#: builtin/remote.c msgid "specifying a master branch makes no sense with --mirror" msgstr "especificar una branca mestra no té sentit amb --mirror" +#: builtin/remote.c msgid "specifying branches to track makes sense only with fetch mirrors" msgstr "" "especificar les branques a seguir té sentit només amb miralls d'obtenció" +#: builtin/remote.c #, c-format msgid "remote %s already exists." msgstr "el remot %s ja existeix." +#: builtin/remote.c #, c-format msgid "Could not setup master '%s'" msgstr "No s'ha pogut configurar la mestra «%s»" +#: builtin/remote.c trailer.c #, c-format msgid "more than one %s" msgstr "més d'un %s" +#: builtin/remote.c #, c-format msgid "unhandled branch.%s.rebase=%s; assuming 'true'" msgstr "no s'ha gestionat branch.%s.rebase=%s; assumint «true»" +#: builtin/remote.c #, c-format msgid "Could not get fetch map for refspec %s" msgstr "" "No s'ha pogut obtenir el mapa d'obtenció de l'especificació de referència %s" +#: builtin/remote.c msgid "(matching)" msgstr "(coincident)" +#: builtin/remote.c msgid "(delete)" msgstr "(suprimir)" +#: builtin/remote.c #, c-format msgid "could not set '%s'" msgstr "no s'ha pogut establir «%s»" +#: builtin/remote.c config.c #, c-format msgid "could not unset '%s'" msgstr "no s'ha pogut desassignar «%s»" +#: builtin/remote.c #, c-format msgid "" "The %s configuration remote.pushDefault in:\n" @@ -10813,14 +13812,17 @@ msgstr "" "\t%s:%d\n" "ara anomena un remot no existent «%s»" +#: builtin/remote.c #, c-format msgid "No such remote: '%s'" msgstr "No existeix el remot «%s»" +#: builtin/remote.c #, c-format msgid "Could not rename config section '%s' to '%s'" msgstr "No s'ha pogut canviar el nom de la secció de configuració «%s» a «%s»" +#: builtin/remote.c #, c-format msgid "" "Not updating non-default fetch refspec\n" @@ -10832,17 +13834,21 @@ msgstr "" "\t%s\n" "\tActualitzeu la configuració manualment si és necessari." +#: builtin/remote.c msgid "Renaming remote references" msgstr "S'està canviant el nom de les referències remotes" +#: builtin/remote.c #, c-format msgid "deleting '%s' failed" msgstr "la supressió de «%s» ha fallat" +#: builtin/remote.c #, c-format msgid "creating '%s' failed" msgstr "la creació de «%s» ha fallat" +#: builtin/remote.c msgid "" "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n" "to delete it, use:" @@ -10857,246 +13863,307 @@ msgstr[1] "" "eliminat;\n" "per a suprimir-les, useu:" +#: builtin/remote.c #, c-format msgid "Could not remove config section '%s'" msgstr "No s'ha pogut eliminar la secció de configuració «%s»" +#: builtin/remote.c #, c-format msgid " new (next fetch will store in remotes/%s)" msgstr " nou (la pròxima obtenció emmagatzemarà a remotes/%s)" +#: builtin/remote.c msgid " tracked" msgstr " seguit" +#: builtin/remote.c msgid " skipped" msgstr " omès" +#: builtin/remote.c msgid " stale (use 'git remote prune' to remove)" msgstr " estancat (useu «git remote prune» per a eliminar)" +#: builtin/remote.c msgid " ???" msgstr " ???" +#: builtin/remote.c #, c-format msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch" msgstr "branch.%s.merge no và lid; no es pot fer «rebase» sobre > 1 branca" +#: builtin/remote.c #, c-format msgid "rebases interactively onto remote %s" msgstr "es fa «rebase» interactivament sobre el remot %s" +#: builtin/remote.c #, c-format msgid "rebases interactively (with merges) onto remote %s" msgstr "es fa «rebase» interactivament (amb fusions) sobre el remot %s" +#: builtin/remote.c #, c-format msgid "rebases onto remote %s" msgstr "es fa «rebase» sobre el remot %s" +#: builtin/remote.c #, c-format msgid " merges with remote %s" msgstr " es fusiona amb el remot %s" +#: builtin/remote.c #, c-format msgid "merges with remote %s" msgstr "es fusiona amb el remot %s" +#: builtin/remote.c #, c-format msgid "%-*s and with remote %s\n" msgstr "%-*s i amb el remot %s\n" +#: builtin/remote.c msgid "create" msgstr "crea" +#: builtin/remote.c msgid "delete" msgstr "suprimeix" +#: builtin/remote.c msgid "up to date" msgstr "al dia" +#: builtin/remote.c msgid "fast-forwardable" msgstr "avanç rà pid possible" +#: builtin/remote.c msgid "local out of date" msgstr "local no actualitzat" +#: builtin/remote.c #, c-format msgid " %-*s forces to %-*s (%s)" msgstr " %-*s força a %-*s (%s)" +#: builtin/remote.c #, c-format msgid " %-*s pushes to %-*s (%s)" msgstr " %-*s puja a %-*s (%s)" +#: builtin/remote.c #, c-format msgid " %-*s forces to %s" msgstr " %-*s força a %s" +#: builtin/remote.c #, c-format msgid " %-*s pushes to %s" msgstr " %-*s puja a %s" +#: builtin/remote.c msgid "do not query remotes" msgstr "no consultis els remots" +#: builtin/remote.c #, c-format msgid "* remote %s" msgstr "* remot %s" +#: builtin/remote.c #, c-format msgid " Fetch URL: %s" msgstr " URL d'obtenció: %s" -msgid "(no URL)" -msgstr "(sense URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. #. +#: builtin/remote.c #, c-format msgid " Push URL: %s" msgstr " URL de pujada: %s" +#: builtin/remote.c +msgid "(no URL)" +msgstr "(sense URL)" + +#: builtin/remote.c #, c-format msgid " HEAD branch: %s" msgstr " Branca de HEAD: %s" +#: builtin/remote.c msgid "(not queried)" msgstr "(no consultat)" +#: builtin/remote.c msgid "(unknown)" msgstr "(desconegut)" +#: builtin/remote.c #, c-format msgid "" " HEAD branch (remote HEAD is ambiguous, may be one of the following):\n" msgstr "" " Branca de HEAD (la HEAD remot és ambigua, pot ser un dels següents):\n" +#: builtin/remote.c #, c-format msgid " Remote branch:%s" msgid_plural " Remote branches:%s" msgstr[0] " Branca remota:%s" msgstr[1] " Branques remotes:%s" +#: builtin/remote.c msgid " (status not queried)" msgstr " (estat no consultat)" +#: builtin/remote.c msgid " Local branch configured for 'git pull':" msgid_plural " Local branches configured for 'git pull':" msgstr[0] " Branca local configurada per a «git pull»:" msgstr[1] " Branques locals configurades per a «git pull»:" +#: builtin/remote.c msgid " Local refs will be mirrored by 'git push'" msgstr " «git push» reflectirà les referències locals" +#: builtin/remote.c #, c-format msgid " Local ref configured for 'git push'%s:" msgid_plural " Local refs configured for 'git push'%s:" msgstr[0] " Referència local configurada per a «git push»%s:" msgstr[1] " Referències locals configurades per a «git push»%s:" +#: builtin/remote.c msgid "set refs/remotes/<name>/HEAD according to remote" msgstr "estableix refs/remotes/<nom>/HEAD segons el remot" +#: builtin/remote.c msgid "delete refs/remotes/<name>/HEAD" msgstr "suprimeix refs/remotes/<nom>/HEAD" +#: builtin/remote.c msgid "Cannot determine remote HEAD" msgstr "No es pot determinar la HEAD remota" +#: builtin/remote.c msgid "Multiple remote HEAD branches. Please choose one explicitly with:" msgstr "Múltiples branques de HEAD remotes. Trieu-ne una explÃcitament amb:" +#: builtin/remote.c #, c-format msgid "Could not delete %s" msgstr "No s'ha pogut suprimir %s" +#: builtin/remote.c #, c-format msgid "Not a valid ref: %s" msgstr "No és una referència và lida: %s" +#: builtin/remote.c #, c-format msgid "Could not setup %s" msgstr "No s'ha pogut configurar %s" +#: builtin/remote.c #, c-format msgid " %s will become dangling!" -msgstr " %s es tornarà penjant!" +msgstr " %s es quedara despenjat!" +#: builtin/remote.c #, c-format msgid " %s has become dangling!" -msgstr " %s s'ha tornat penjant!" +msgstr " %s s'ha quedat despenjat!" +#: builtin/remote.c #, c-format msgid "Pruning %s" msgstr "S'està podant %s" +#: builtin/remote.c #, c-format msgid "URL: %s" msgstr "URL: %s" +#: builtin/remote.c #, c-format msgid " * [would prune] %s" msgstr " * [podaria] %s" +#: builtin/remote.c #, c-format msgid " * [pruned] %s" msgstr " * [podat] %s" +#: builtin/remote.c msgid "prune remotes after fetching" msgstr "poda els remots després d'obtenir-los" +#: builtin/remote.c #, c-format msgid "No such remote '%s'" msgstr "No hi ha tal remot «%s»" +#: builtin/remote.c msgid "add branch" msgstr "afegeix branca" +#: builtin/remote.c msgid "no remote specified" msgstr "cap remot especificat" +#: builtin/remote.c msgid "query push URLs rather than fetch URLs" msgstr "consulta els URL de pujada en lloc dels URL d'obtenció" +#: builtin/remote.c msgid "return all URLs" msgstr "retorna tots els URL" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "cap URL configurat per al remot «%s»" - +#: builtin/remote.c msgid "manipulate push URLs" msgstr "manipula els URL de pujada" +#: builtin/remote.c msgid "add URL" msgstr "afegeix URL" +#: builtin/remote.c msgid "delete URLs" msgstr "suprimeix els URL" +#: builtin/remote.c msgid "--add --delete doesn't make sense" msgstr "--add --delete no té sentit" +#: builtin/remote.c #, c-format msgid "Invalid old URL pattern: %s" msgstr "Patró d'URL antic no và lid: %s" +#: builtin/remote.c #, c-format msgid "No such URL found: %s" msgstr "No s'ha trobat tal URL: %s" +#: builtin/remote.c msgid "Will not delete all non-push URLs" msgstr "No se suprimiran tots els URL no de pujada" +#: builtin/remote.c msgid "be verbose; must be placed before a subcommand" msgstr "sigues detallat; s'ha de col·locar abans d'una subordre" +#: builtin/repack.c msgid "git repack [<options>]" msgstr "git repack [<opcions>]" +#: builtin/repack.c msgid "" "Incremental repacks are incompatible with bitmap indexes. Use\n" "--no-write-bitmap-index or disable the pack.writeBitmaps configuration." @@ -11106,173 +14173,225 @@ msgstr "" "--no-write-bitmap-index o inhabiliteu el parà metre de configuració pack." "writeBitmaps." +#: builtin/repack.c msgid "could not start pack-objects to repack promisor objects" msgstr "" "no s'ha pogut iniciar pack-objects per a tornar a empaquetar els objectes " "«promisor»" +#: builtin/repack.c +msgid "failed to feed promisor objects to pack-objects" +msgstr "no s'ha pogut alimentar pack-objects amb objectes «promisor»" + +#: builtin/repack.c msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack: s'esperen només lÃnies amb l'id d'objecte hexadecimal complet des de " "pack-objects." +#: builtin/repack.c msgid "could not finish pack-objects to repack promisor objects" msgstr "" "no s'ha pogut finalitzar pack-objects per a tornar a empaquetar els objectes " "«promisor»" +#: builtin/repack.c #, c-format msgid "cannot open index for %s" msgstr "no s'ha pogut obrir l'Ãndex per a %s" +#: builtin/repack.c #, c-format msgid "pack %s too large to consider in geometric progression" msgstr "" "el paquet %s és massa gran per a considerar-ho en progressió geomètrica" +#: builtin/repack.c #, c-format msgid "pack %s too large to roll up" msgstr "el paquet %s és massa gran per a enrotllar-lo" +#: builtin/repack.c #, c-format msgid "could not open tempfile %s for writing" msgstr "no s'ha pogut obrir el fitxer temporal «%s» per a escriptura" +#: builtin/repack.c msgid "could not close refs snapshot tempfile" msgstr "" "no s'ha pogut tancar el fitxer temporal amb la instantà nia de referències" +#: builtin/repack.c #, c-format msgid "could not remove stale bitmap: %s" msgstr "no s'ha pogut eliminar el mapa de bits estancat: %s" +#: builtin/repack.c #, c-format msgid "pack prefix %s does not begin with objdir %s" msgstr "el prefix de paquet %s no comença amb objdir %s" +#: builtin/repack.c msgid "pack everything in a single pack" msgstr "empaqueta-ho tot en un únic paquet" +#: builtin/repack.c msgid "same as -a, and turn unreachable objects loose" msgstr "el mateix que -a, i solta els objectes inabastables" +#: builtin/repack.c msgid "same as -a, pack unreachable cruft objects separately" msgstr "" "el mateix que -a, empaqueta els objectes superflus inabastables de forma " "separada" +#: builtin/repack.c msgid "approxidate" msgstr "data aproximada" +#: builtin/repack.c msgid "with --cruft, expire objects older than this" msgstr "amb --cruft, vencen els objectes més antics que aquest" +#: builtin/repack.c msgid "remove redundant packs, and run git-prune-packed" msgstr "elimina els paquets redundants, i executeu git-prune-packed" +#: builtin/repack.c msgid "pass --no-reuse-delta to git-pack-objects" msgstr "passa --no-reuse-delta a git-pack-objects" +#: builtin/repack.c msgid "pass --no-reuse-object to git-pack-objects" msgstr "passa --no-reuse-object a git-pack-objects" +#: builtin/repack.c msgid "do not run git-update-server-info" msgstr "no executis git-update-server-info" +#: builtin/repack.c msgid "pass --local to git-pack-objects" msgstr "passa --local a git-pack-objects" +#: builtin/repack.c msgid "write bitmap index" msgstr "escriu Ãndex de mapa de bits" +#: builtin/repack.c msgid "pass --delta-islands to git-pack-objects" msgstr "passa --delta-islands a git-pack-objects" +#: builtin/repack.c msgid "with -A, do not loosen objects older than this" msgstr "amb -A, no soltis els objectes més antics que aquest" +#: builtin/repack.c msgid "with -a, repack unreachable objects" msgstr "amb -a, reempaqueta els objectes inabastables" +#: builtin/repack.c msgid "size of the window used for delta compression" msgstr "mida de la finestra que s'usa per a compressió de diferències" +#: builtin/repack.c msgid "bytes" msgstr "octets" +#: builtin/repack.c msgid "same as the above, but limit memory size instead of entries count" msgstr "" "el mateix que l'anterior, però limita la mida de memòria en lloc del nombre " "d'entrades" +#: builtin/repack.c msgid "limits the maximum delta depth" msgstr "limita la profunditat mà xima de les diferències" +#: builtin/repack.c msgid "limits the maximum number of threads" msgstr "limita el nombre mà xim de fils" +#: builtin/repack.c msgid "maximum size of each packfile" msgstr "mida mà xima de cada fitxer de paquet" +#: builtin/repack.c msgid "repack objects in packs marked with .keep" msgstr "reempaqueta els objectes en paquets marcats amb .keep" +#: builtin/repack.c msgid "do not repack this pack" msgstr "no reempaquetis aquest paquet" +#: builtin/repack.c msgid "find a geometric progression with factor <N>" msgstr "troba una progressió geomètrica amb el factor <N>" +#: builtin/repack.c msgid "write a multi-pack index of the resulting packs" msgstr "escriu un Ãndex multipaquet dels paquets resultants" +#: builtin/repack.c msgid "pack prefix to store a pack containing pruned objects" msgstr "" "prefix del paquet per a emmagatzemar un paquet que contingui objectes podats" +#: builtin/repack.c msgid "pack prefix to store a pack containing filtered out objects" msgstr "" "prefix del paquet per a emmagatzemar un paquet que contingui objectes " "filtrats" +#: builtin/repack.c msgid "cannot delete packs in a precious-objects repo" msgstr "no es poden suprimir paquets en un repositori d'objectes preciosos" +#: builtin/repack.c #, c-format msgid "option '%s' can only be used along with '%s'" msgstr "l'opció «%s» només es pot utilitzar juntament amb «%s»" +#: builtin/repack.c msgid "Nothing new to pack." msgstr "Res nou a empaquetar." +#: builtin/repack.c #, c-format msgid "renaming pack to '%s' failed" msgstr "el canvi del nom a «%s» ha fallat" +#: builtin/repack.c #, c-format msgid "pack-objects did not write a '%s' file for pack %s-%s" msgstr "" "els objectes de paquet no han escrit a un fitxer «%s» per al paquet %s-%s" +#: builtin/repack.c sequencer.c #, c-format msgid "could not unlink: %s" msgstr "no s'ha pogut desenllaçar: «%s»" +#: builtin/replace.c msgid "git replace [-f] <object> <replacement>" msgstr "git replace [-f] <objecte> <reemplaçament>" +#: builtin/replace.c msgid "git replace [-f] --edit <object>" msgstr "git replace [-f] --edit <objecte>" +#: builtin/replace.c msgid "git replace [-f] --graft <commit> [<parent>...]" msgstr "git replace [-f] --graft <comissió> [<pare>...]" +#: builtin/replace.c msgid "git replace -d <object>..." msgstr "git replace -d <objecte>..." +#: builtin/replace.c msgid "git replace [--format=<format>] [-l [<pattern>]]" msgstr "git replace [--format=<format>] [-l [<patró>]]" +#: builtin/replace.c #, c-format msgid "" "invalid replace format '%s'\n" @@ -11281,22 +14400,27 @@ msgstr "" "format de reemplaçament no và lid «%s»\n" "els formats và lids són «short» «medium» i «long»" +#: builtin/replace.c #, c-format msgid "replace ref '%s' not found" msgstr "no s'ha trobat la referència de reemplaçament '«%s»" +#: builtin/replace.c #, c-format msgid "Deleted replace ref '%s'" msgstr "S'ha suprimit la referència «%s»" +#: builtin/replace.c #, c-format msgid "'%s' is not a valid ref name" msgstr "«%s» no és un nom de referència và lid" +#: builtin/replace.c #, c-format msgid "replace ref '%s' already exists" msgstr "la referència de reemplaçament «%s» ja existeix" +#: builtin/replace.c #, c-format msgid "" "Objects must be of the same type.\n" @@ -11307,59 +14431,75 @@ msgstr "" "«%s» apunta a un objecte substituït del tipus «%s»\n" "mentre que «%s» apunta a un objecte de substitució del tipus «%s»." +#: builtin/replace.c #, c-format msgid "unable to open %s for writing" msgstr "no s'ha pogut obrir %s per a escriptura" +#: builtin/replace.c msgid "cat-file reported failure" msgstr "cat-file ha informat d'un error" +#: builtin/replace.c #, c-format msgid "unable to open %s for reading" msgstr "no s'ha pogut obrir %s per a lectura" +#: builtin/replace.c msgid "unable to spawn mktree" msgstr "no s'ha pogut engendrar el mktree" +#: builtin/replace.c msgid "unable to read from mktree" msgstr "no s'ha pogut llegir des de mktree" +#: builtin/replace.c msgid "mktree reported failure" msgstr "mktree ha informat d'una fallada" +#: builtin/replace.c msgid "mktree did not return an object name" msgstr "mktree no ha retornat un nom d'objecte" +#: builtin/replace.c #, c-format msgid "unable to fstat %s" msgstr "no s'ha pogut fer fstat %s" +#: builtin/replace.c msgid "unable to write object to database" msgstr "no s'ha pogut escriure l'objecte a la base de dades" +#: builtin/replace.c #, c-format msgid "unable to get object type for %s" msgstr "no s'ha pogut obtenir el tipus d'objecte per a %s" +#: builtin/replace.c msgid "editing object file failed" msgstr "l'edició del fitxer d'objecte ha fallat" +#: builtin/replace.c #, c-format msgid "new object is the same as the old one: '%s'" msgstr "l'objecte nou és el mateix que l'antic: «%s»" +#: builtin/replace.c #, c-format msgid "could not parse %s as a commit" msgstr "no s'ha pogut analitzar %s com a comissió" +#: builtin/replace.c #, c-format msgid "bad mergetag in commit '%s'" msgstr "etiqueta de fusió incorrecta en la comissió «%s»" +#: builtin/replace.c #, c-format msgid "malformed mergetag in commit '%s'" msgstr "etiqueta de fusió mal formada en la comissió «%s»" +#: builtin/replace.c #, c-format msgid "" "original commit '%s' contains mergetag '%s' that is discarded; use --edit " @@ -11368,25 +14508,31 @@ msgstr "" "la comissió original «%s» conté l'etiqueta de fusió «%s» que es descarta; " "useu --edit en lloc de --graft" +#: builtin/replace.c #, c-format msgid "the original commit '%s' has a gpg signature" msgstr "la comissió original «%s» té una signatura gpg" +#: builtin/replace.c msgid "the signature will be removed in the replacement commit!" msgstr "s'eliminarà la signatura en la comissió de reemplaçament!" +#: builtin/replace.c #, c-format msgid "could not write replacement commit for: '%s'" msgstr "no s'ha pogut escriure la comissió de reemplaçament per a: «%s»" +#: builtin/replace.c #, c-format msgid "graft for '%s' unnecessary" msgstr "«graft» per a «%s» innecessari" +#: builtin/replace.c #, c-format msgid "new commit is the same as the old one: '%s'" msgstr "la comissió nova és la mateixa que l'antiga: «%s»" +#: builtin/replace.c #, c-format msgid "" "could not convert the following graft(s):\n" @@ -11395,69 +14541,91 @@ msgstr "" "no s'han pogut convertir els següents «grafts»:\n" "%s" +#: builtin/replace.c msgid "list replace refs" msgstr "llista les referències de reemplaçament" +#: builtin/replace.c msgid "delete replace refs" msgstr "suprimeix les referències de reemplaçament" +#: builtin/replace.c msgid "edit existing object" msgstr "edita un objecte existent" +#: builtin/replace.c msgid "change a commit's parents" msgstr "canvia els pares d'una comissió" +#: builtin/replace.c msgid "convert existing graft file" msgstr "converteix el fitxer «graft» existent" +#: builtin/replace.c msgid "replace the ref if it exists" msgstr "reemplaça la referència si existeix" +#: builtin/replace.c msgid "do not pretty-print contents for --edit" msgstr "no imprimeixis bellament els continguts per a --edit" +#: builtin/replace.c msgid "use this format" msgstr "usa aquest format" +#: builtin/replace.c msgid "--format cannot be used when not listing" msgstr "no es pot utilitzar «--format» quan no s'està llistant" +#: builtin/replace.c msgid "-f only makes sense when writing a replacement" msgstr "-f només té sentit quan s'escriu un reemplaçament" +#: builtin/replace.c msgid "--raw only makes sense with --edit" msgstr "--raw només té sentit amb --edit" +#: builtin/replace.c msgid "-d needs at least one argument" msgstr "-d necessita almenys un argument" +#: builtin/replace.c msgid "bad number of arguments" msgstr "nombre incorrecte d'arguments" +#: builtin/replace.c msgid "-e needs exactly one argument" msgstr "-e necessita exactament un argument" +#: builtin/replace.c msgid "-g needs at least one argument" msgstr "-g necessita almenys un argument" +#: builtin/replace.c msgid "--convert-graft-file takes no argument" msgstr "--convert-graft-file arguments" +#: builtin/replace.c msgid "only one pattern can be given with -l" msgstr "només es pot especificar un patró amb -l" +#: builtin/replay.c msgid "need some commits to replay" msgstr "calen algunes comissions per tornar a reproduir" +#: builtin/replay.c msgid "--onto and --advance are incompatible" msgstr "--onto i --advance són incompatibles" +#: builtin/replay.c msgid "all positive revisions given must be references" msgstr "totes les revisions positives que s'han donat han de ser referències" +#: builtin/replay.c msgid "argument to --advance must be a reference" msgstr "l'argument per a --advance ha de ser una referència" +#: builtin/replay.c msgid "" "cannot advance target with multiple sources because ordering would be ill-" "defined" @@ -11465,12 +14633,14 @@ msgstr "" "no es pot avançar l'objectiu amb múltiples fonts perquè l'ordenació no " "estaria definida correctament" +#: builtin/replay.c msgid "" "cannot implicitly determine whether this is an --advance or --onto operation" msgstr "" "no es pot determinar implÃcitament si aquesta és una operació --advance o --" "onto" +#: builtin/replay.c msgid "" "cannot advance target with multiple source branches because ordering would " "be ill-defined" @@ -11478,9 +14648,11 @@ msgstr "" "no es pot avançar l'objectiu amb múltiples branques d'origen perquè " "l'ordenació no estaria definida correctament" +#: builtin/replay.c msgid "cannot implicitly determine correct base for --onto" msgstr "no es pot determinar implÃcitament la base correcta per a --onto" +#: builtin/replay.c msgid "" "(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance " "<branch>) <revision-range>..." @@ -11488,18 +14660,23 @@ msgstr "" "(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance " "<branch>) <revision-range>..." +#: builtin/replay.c msgid "make replay advance given branch" msgstr "fes avançar la repetició de la branca donada" +#: builtin/replay.c msgid "replay onto given commit" msgstr "torna a reproduir a la comissió donada" +#: builtin/replay.c msgid "advance all branches contained in revision-range" msgstr "avança totes les branques contingudes a l'interval de revisions" +#: builtin/replay.c msgid "option --onto or --advance is mandatory" msgstr "l'opció --onto o --advance és obligatòria" +#: builtin/replay.c #, c-format msgid "" "some rev walking options will be overridden as '%s' bit in 'struct rev_info' " @@ -11508,124 +14685,159 @@ msgstr "" "algunes opcions de referència se sobreescriuran de forma forçada com a «%s» " "bits a «struct rev_info»" +#: builtin/replay.c msgid "error preparing revisions" msgstr "s'ha produït un error en preparar les revisions" +#: builtin/replay.c msgid "replaying down to root commit is not supported yet!" msgstr "encara no s'admet la reproducció cap avall en una comissió arrel" +#: builtin/replay.c msgid "replaying merge commits is not supported yet!" -msgstr "encara no s'admet la repetició de les comissió de fusió" +msgstr "encara no s'admet la repetició de les comissions de fusió" +#: builtin/rerere.c msgid "" "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]" msgstr "" "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]" +#: builtin/rerere.c msgid "register clean resolutions in index" msgstr "registra les resolucions netes en l'Ãndex" +#: builtin/rerere.c msgid "'git rerere forget' without paths is deprecated" msgstr "«git rerere forget» sense camins està en desús" +#: builtin/rerere.c #, c-format msgid "unable to generate diff for '%s'" msgstr "no s'ha pogut generar el diff per a «%s»" +#: builtin/reset.c msgid "" "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" msgstr "" "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<comissió>]" +#: builtin/reset.c msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..." msgstr "git reset [-q] [<tree-ish>] [--] <pathspec>..." +#: builtin/reset.c msgid "" "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" msgstr "" "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" +#: builtin/reset.c msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]" msgstr "git reset --patch [<tree-ish>] [--] [<pathspec>...]" +#: builtin/reset.c msgid "mixed" msgstr "mixt" +#: builtin/reset.c msgid "soft" msgstr "suau" +#: builtin/reset.c msgid "hard" msgstr "dur" +#: builtin/reset.c msgid "merge" msgstr "fusió" +#: builtin/reset.c msgid "keep" msgstr "reteniment" +#: builtin/reset.c msgid "You do not have a valid HEAD." msgstr "No teniu una HEAD và lida." +#: builtin/reset.c msgid "Failed to find tree of HEAD." msgstr "S'ha produït un error en trobar l'arbre de HEAD." +#: builtin/reset.c #, c-format msgid "Failed to find tree of %s." msgstr "S'ha produït un error en cercar l'arbre de %s." +#: builtin/reset.c #, c-format msgid "HEAD is now at %s" msgstr "HEAD ara és a %s" +#: builtin/reset.c #, c-format msgid "Cannot do a %s reset in the middle of a merge." msgstr "No es pot fer un restabliment de %s enmig d'una fusió." +#: builtin/reset.c builtin/stash.c msgid "be quiet, only report errors" msgstr "sigues silenciós, només informa d'errors" +#: builtin/reset.c msgid "skip refreshing the index after reset" msgstr "omet l'actualització de l'Ãndex després de reiniciar" +#: builtin/reset.c msgid "reset HEAD and index" msgstr "restableix HEAD i l'Ãndex" +#: builtin/reset.c msgid "reset only HEAD" msgstr "restableix només HEAD" +#: builtin/reset.c msgid "reset HEAD, index and working tree" msgstr "restableix HEAD, l'Ãndex i l'arbre de treball" +#: builtin/reset.c msgid "reset HEAD but keep local changes" msgstr "restableix HEAD però retén els canvis locals" +#: builtin/reset.c msgid "record only the fact that removed paths will be added later" msgstr "registra només el fet que els camins eliminats s'afegiran després" +#: builtin/reset.c #, c-format msgid "Failed to resolve '%s' as a valid revision." msgstr "S'ha produït un error en resoldre «%s» com a revisió và lida." +#: builtin/reset.c #, c-format msgid "Failed to resolve '%s' as a valid tree." msgstr "S'ha produït un error en resoldre «%s» com a arbre và lid." +#: builtin/reset.c msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead." msgstr "" "--mixed amb camins està en desús; useu «git reset -- <camins>» en lloc " "d'això." +#: builtin/reset.c #, c-format msgid "Cannot do %s reset with paths." msgstr "No es pot restablir de %s amb camins." +#: builtin/reset.c #, c-format msgid "%s reset is not allowed in a bare repository" msgstr "el restabliment de %s no es permet en un repositori nu" +#: builtin/reset.c msgid "Unstaged changes after reset:" msgstr "Canvis «unstaged» després del restabliment:" +#: builtin/reset.c #, c-format msgid "" "It took %.2f seconds to refresh the index after reset. You can use\n" @@ -11635,52 +14847,67 @@ msgstr "" "usar\n" ".--no-refresh' per a evitar això." +#: builtin/reset.c #, c-format msgid "Could not reset index file to revision '%s'." msgstr "No s'ha pogut restablir el fitxer d'Ãndex a la revisió «%s»." +#: builtin/reset.c msgid "Could not write new index file." msgstr "No s'ha pogut escriure el fitxer d'Ãndex nou." +#: builtin/rev-list.c #, c-format msgid "unable to get disk usage of %s" msgstr "no s'ha pogut obtenir l'ús del disc de %s" +#: builtin/rev-list.c #, c-format msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "valor no và lid per a «%s»: «%s», l'únic format permès és «%s»" +#: builtin/rev-list.c msgid "rev-list does not support display of notes" msgstr "el rev-list no permet mostrar notes" +#: builtin/rev-list.c #, c-format msgid "marked counting and '%s' cannot be used together" msgstr "«marked counting» i «%s» no es poden usar junts" +#: builtin/rev-parse.c msgid "git rev-parse --parseopt [<options>] -- [<args>...]" msgstr "git rev-parse --parseopt [<opcions>] -- [<arguments>...]" +#: builtin/rev-parse.c msgid "keep the `--` passed as an arg" msgstr "retén el «--» passat com a argument" +#: builtin/rev-parse.c msgid "stop parsing after the first non-option argument" msgstr "deixa d'analitzar després del primer argument que no sigui d'opció" +#: builtin/rev-parse.c msgid "output in stuck long form" msgstr "emet en forma llarga enganxada" +#: builtin/rev-parse.c msgid "premature end of input" msgstr "final prematur de l'entrada" +#: builtin/rev-parse.c msgid "no usage string given before the `--' separator" msgstr "no s'ha indicat cap cadena d'ús abans del separador «--»" +#: builtin/rev-parse.c msgid "missing opt-spec before option flags" msgstr "manca l'opció opt-spec abans de les altres opcions" +#: builtin/rev-parse.c msgid "Needed a single revision" msgstr "Cal una sola revisió" +#: builtin/rev-parse.c msgid "" "git rev-parse --parseopt [<options>] -- [<args>...]\n" " or: git rev-parse --sq-quote [<arg>...]\n" @@ -11695,46 +14922,68 @@ msgstr "" "Executeu «git rev-parse --parseopt -h» per a més informació sobre el primer " "ús." +#: builtin/rev-parse.c msgid "--resolve-git-dir requires an argument" msgstr "--resolve-git-dir requereix un argument" +#: builtin/rev-parse.c #, c-format msgid "not a gitdir '%s'" msgstr "no és un directori git «%s»" +#: builtin/rev-parse.c msgid "--git-path requires an argument" msgstr "--git-path requereix un argument" +#: builtin/rev-parse.c msgid "-n requires an argument" msgstr "-n requereix un argument" +#: builtin/rev-parse.c msgid "--path-format requires an argument" msgstr "--path-format requereix un argument" +#: builtin/rev-parse.c #, c-format msgid "unknown argument to --path-format: %s" msgstr "argument no và lid per a --path-format: %s" +#: builtin/rev-parse.c msgid "--default requires an argument" msgstr "--default requereix un argument" +#: builtin/rev-parse.c msgid "--prefix requires an argument" msgstr "--prefix requereix un argument" +#: builtin/rev-parse.c +msgid "no object format specified" +msgstr "no s'ha especificat cap format d'objecte" + +#: builtin/rev-parse.c +#, c-format +msgid "unsupported object format: %s" +msgstr "format d'objecte no compatible: %s" + +#: builtin/rev-parse.c #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "mode desconegut per a --abbrev-ref: %s" +#: builtin/rev-parse.c setup.c msgid "this operation must be run in a work tree" msgstr "aquesta operació s'ha d'executar en un arbre de treball" +#: builtin/rev-parse.c msgid "Could not read the index" msgstr "No s'ha pogut llegir l'Ãndex" +#: builtin/rev-parse.c #, c-format msgid "unknown mode for --show-object-format: %s" msgstr "mode desconegut per a --show-object-format: %s" +#: builtin/revert.c msgid "" "git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] " "<commit>..." @@ -11742,9 +14991,11 @@ msgstr "" "git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] " "<comissió>..." +#: builtin/revert.c msgid "git revert (--continue | --skip | --abort | --quit)" msgstr "git revert (--continue | --skip | --abort | --quit)" +#: builtin/revert.c msgid "" "git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" " [-S[<keyid>]] <commit>..." @@ -11752,68 +15003,89 @@ msgstr "" "git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" " [-S[<keyid>]] <comissió>..." +#: builtin/revert.c msgid "git cherry-pick (--continue | --skip | --abort | --quit)" msgstr "git cherry-pick (--continue | --skip | --abort | --quit)" +#: builtin/revert.c #, c-format msgid "option `%s' expects a number greater than zero" msgstr "l'opció «%s» espera un nombre major que zero" +#: builtin/revert.c #, c-format msgid "%s: %s cannot be used with %s" msgstr "%s: %s no es pot usar amb %s" +#: builtin/revert.c msgid "end revert or cherry-pick sequence" msgstr "acaba la seqüència de reversió o el «cherry pick»" +#: builtin/revert.c msgid "resume revert or cherry-pick sequence" msgstr "reprèn la seqüència de reversió o el «cherry pick»" +#: builtin/revert.c msgid "cancel revert or cherry-pick sequence" msgstr "cancel·la la seqüència de reversió o el «cherry pick»" +#: builtin/revert.c msgid "skip current commit and continue" msgstr "omet la comissió actual i continua" +#: builtin/revert.c msgid "don't automatically commit" msgstr "no cometis automà ticament" +#: builtin/revert.c msgid "edit the commit message" msgstr "edita el missatge de comissió" +#: builtin/revert.c msgid "parent-number" msgstr "número del pare" +#: builtin/revert.c msgid "select mainline parent" msgstr "selecciona la lÃnia principal del pare" +#: builtin/revert.c msgid "merge strategy" msgstr "estratègia de fusió" +#: builtin/revert.c msgid "option for merge strategy" msgstr "opció d'estratègia de fusió" +#: builtin/revert.c msgid "append commit name" msgstr "nom de la comissió a annexar" +#: builtin/revert.c msgid "preserve initially empty commits" msgstr "conserva les comissions inicialment buides" +#: builtin/revert.c msgid "allow commits with empty messages" msgstr "permet les comissions amb missatges buits" -msgid "keep redundant, empty commits" -msgstr "retén les comissions redundants i buides" +#: builtin/revert.c +msgid "deprecated: use --empty=keep instead" +msgstr "obsolet: utilitzeu --empty=keep en el seu lloc" +#: builtin/revert.c msgid "use the 'reference' format to refer to commits" msgstr "useu el format «referència» per a referir-vos a les comissions" +#: builtin/revert.c msgid "revert failed" msgstr "la reversió ha fallat" +#: builtin/revert.c msgid "cherry-pick failed" msgstr "el «cherry pick» ha fallat" +#: builtin/rm.c msgid "" "git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n" " [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" @@ -11823,6 +15095,7 @@ msgstr "" " [--quiet] [--pathspec-from-file=<fitxer> [--pathspec-file-nul]]\n" " [--] [<pathspec>...]" +#: builtin/rm.c msgid "" "the following file has staged content different from both the\n" "file and the HEAD:" @@ -11830,12 +15103,13 @@ msgid_plural "" "the following files have staged content different from both the\n" "file and the HEAD:" msgstr[0] "" -"el fitxer següent té contingut «staged» diferent al fitxer\n" -"i a HEAD:" +"el fitxer següent té contingut «staged» diferent del fitxer\n" +"i de HEAD:" msgstr[1] "" "els fitxers següents tenen contingut «staged» diferent al fitxer\n" "i a HEAD:" +#: builtin/rm.c msgid "" "\n" "(use -f to force removal)" @@ -11843,11 +15117,13 @@ msgstr "" "\n" "(useu -f per a forçar l'eliminació)" +#: builtin/rm.c msgid "the following file has changes staged in the index:" msgid_plural "the following files have changes staged in the index:" msgstr[0] "el fitxer següent té canvis «staged» en l'Ãndex:" msgstr[1] "els fitxers següents tenen canvis «staged» en l'Ãndex:" +#: builtin/rm.c msgid "" "\n" "(use --cached to keep the file, or -f to force removal)" @@ -11855,42 +15131,53 @@ msgstr "" "\n" "(useu --cached per a mantenir el fitxer, o -f per a forçar l'eliminació)" +#: builtin/rm.c msgid "the following file has local modifications:" msgid_plural "the following files have local modifications:" msgstr[0] "el fitxer següent té modificacions locals:" msgstr[1] "els fitxers següents tenen modificacions locals:" +#: builtin/rm.c msgid "do not list removed files" msgstr "no llistis els fitxers eliminats" +#: builtin/rm.c msgid "only remove from the index" msgstr "només elimina de l'Ãndex" +#: builtin/rm.c msgid "override the up-to-date check" msgstr "passa per alt la comprovació d'actualitat" +#: builtin/rm.c msgid "allow recursive removal" msgstr "permet l'eliminació recursiva" +#: builtin/rm.c msgid "exit with a zero status even if nothing matched" msgstr "surt amb estat zero encara que res hagi coincidit" +#: builtin/rm.c msgid "No pathspec was given. Which files should I remove?" msgstr "" "No s'ha indicat cap especificació de camÃ. Quins fitxers s'han de suprimir?" +#: builtin/rm.c msgid "please stage your changes to .gitmodules or stash them to proceed" msgstr "" "feu un «stage» dels canvis a .gitmodules o feu un «stash» per a continuar" +#: builtin/rm.c #, c-format msgid "not removing '%s' recursively without -r" msgstr "no s'eliminarà «%s» recursivament sense -r" +#: builtin/rm.c #, c-format msgid "git rm: unable to remove %s" msgstr "git rm: no s'ha pogut eliminar %s" +#: builtin/send-pack.c msgid "" "git send-pack [--mirror] [--dry-run] [--force]\n" " [--receive-pack=<git-receive-pack>]\n" @@ -11902,69 +15189,89 @@ msgstr "" " [--receive-pack=<git-receive-pack>]\n" " [--verbose] [--thin] [--atomic]\n" " [--[no-]signed | --signed=(true|false|if-asked)]\n" -" [<host>:]<directory> (--all | <ref>...)" +" [<host>:]<directori> (--all | <referència>...)" +#: builtin/send-pack.c msgid "remote name" msgstr "nom del remot" +#: builtin/send-pack.c msgid "push all refs" msgstr "puja totes les referències" +#: builtin/send-pack.c msgid "use stateless RPC protocol" msgstr "usa el protocol RPC sense estat" +#: builtin/send-pack.c msgid "read refs from stdin" msgstr "llegeix les referències des de stdin" +#: builtin/send-pack.c msgid "print status from remote helper" msgstr "imprimeix l'estat des de l'ajudant remot" +#: builtin/shortlog.c msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]" msgstr "git shortlog [<opcions>] [<rang-de-revisions>] [[--] <camÃ>...]" +#: builtin/shortlog.c msgid "git log --pretty=short | git shortlog [<options>]" msgstr "git log --pretty=short | git shortlog [<opcions>]" +#: builtin/shortlog.c msgid "using multiple --group options with stdin is not supported" msgstr "no s'admet l'ús de múltiples opcions --group amb stdin" +#: builtin/shortlog.c #, c-format msgid "using %s with stdin is not supported" msgstr "no s'admet l'ús de %s amb stdin" +#: builtin/shortlog.c #, c-format msgid "unknown group type: %s" msgstr "tipus de grup desconegut: %s" +#: builtin/shortlog.c msgid "group by committer rather than author" msgstr "agrupa per «committer» en comptes de per autor" +#: builtin/shortlog.c msgid "sort output according to the number of commits per author" msgstr "ordena la sortida segons el nombre de comissions per autor" +#: builtin/shortlog.c msgid "suppress commit descriptions, only provides commit count" msgstr "" "omet les descripcions de les comissions, només proveeix el recompte de " "comissions" +#: builtin/shortlog.c msgid "show the email address of each author" msgstr "mostra l'adreça electrònica de cada autor" +#: builtin/shortlog.c msgid "<w>[,<i1>[,<i2>]]" msgstr "<w>[,<i1>[,<i2>]]" +#: builtin/shortlog.c msgid "linewrap output" msgstr "ajusta les lÃnies de la sortida" +#: builtin/shortlog.c msgid "field" msgstr "camp" +#: builtin/shortlog.c msgid "group by field" msgstr "agrupa per camp" +#: builtin/shortlog.c msgid "too many arguments given outside repository" msgstr "hi ha massa arguments donats fora del repositori" +#: builtin/show-branch.c msgid "" "git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n" " [--current] [--color[=<when>] | --no-color] [--sparse]\n" @@ -11976,114 +15283,144 @@ msgstr "" " [--current] [--color[=<when>] | --no-color] [--sparse]\n" " [--more=<n> | --list | --independent | --merge-base]\n" " [--no-name | --sha1-name] [--topics]\n" -" [(<rev> | <glob>)...]" +" [(<revisió> | <glob>)...]" +#: builtin/show-branch.c msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]" msgstr "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<referència>]" +#: builtin/show-branch.c #, c-format msgid "ignoring %s; cannot handle more than %d ref" msgid_plural "ignoring %s; cannot handle more than %d refs" msgstr[0] "s'està ignorant %s; no es pot gestionar més de %d referència" msgstr[1] "s'està ignorant %s; no es poden gestionar més de %d referències" +#: builtin/show-branch.c #, c-format msgid "no matching refs with %s" msgstr "no hi ha referències coincidents amb %s" +#: builtin/show-branch.c msgid "show remote-tracking and local branches" msgstr "mostra les branques amb seguiment remot i les locals" +#: builtin/show-branch.c msgid "show remote-tracking branches" msgstr "mostra les branques amb seguiment remot" +#: builtin/show-branch.c msgid "color '*!+-' corresponding to the branch" msgstr "colora «*!+-» corresponent a la branca" +#: builtin/show-branch.c msgid "show <n> more commits after the common ancestor" msgstr "mostra <n> comissions després de l'avantpassat comú" +#: builtin/show-branch.c msgid "synonym to more=-1" msgstr "sinònim de more=-1" +#: builtin/show-branch.c msgid "suppress naming strings" msgstr "omet anomenar cadenes" +#: builtin/show-branch.c msgid "include the current branch" msgstr "inclou la branca actual" +#: builtin/show-branch.c msgid "name commits with their object names" msgstr "anomena les comissions amb els seus noms d'objecte" +#: builtin/show-branch.c msgid "show possible merge bases" msgstr "mostra les bases de fusió possibles" +#: builtin/show-branch.c msgid "show refs unreachable from any other ref" msgstr "mostra les referències inabastables de qualsevol altra referència" +#: builtin/show-branch.c msgid "show commits in topological order" msgstr "mostra les comissions en ordre topològic" +#: builtin/show-branch.c msgid "show only commits not on the first branch" msgstr "mostra només les comissions que no siguin en la primera branca" +#: builtin/show-branch.c msgid "show merges reachable from only one tip" msgstr "mostra les fusions abastables de només una punta" +#: builtin/show-branch.c msgid "topologically sort, maintaining date order where possible" msgstr "ordena topològicament, mantenint l'ordre de dates on sigui possible" +#: builtin/show-branch.c msgid "<n>[,<base>]" msgstr "<n>[,<base>]" +#: builtin/show-branch.c msgid "show <n> most recent ref-log entries starting at base" msgstr "mostra les <n> entrades més recents començant a la base" +#: builtin/show-branch.c msgid "no branches given, and HEAD is not valid" msgstr "no s'ha donat cap branca, i HEAD no és và lid" +#: builtin/show-branch.c msgid "--reflog option needs one branch name" msgstr "l'opció --reflog necessita un nom de branca" +#: builtin/show-branch.c #, c-format msgid "only %d entry can be shown at one time." msgid_plural "only %d entries can be shown at one time." msgstr[0] "es pot mostrar només %d entrada a la vegada." msgstr[1] "es poden mostrar només %d entrades a la vegada." +#: builtin/show-branch.c #, c-format msgid "no such ref %s" msgstr "no hi ha tal referència %s" +#: builtin/show-branch.c #, c-format msgid "cannot handle more than %d rev." msgid_plural "cannot handle more than %d revs." msgstr[0] "no es pot gestionar més d'%d revisió." msgstr[1] "no es poden gestionar més de %d revisions." +#: builtin/show-branch.c #, c-format msgid "'%s' is not a valid ref." msgstr "«%s» no és una referència và lida." +#: builtin/show-branch.c #, c-format msgid "cannot find commit %s (%s)" msgstr "no es pot trobar la comissió %s (%s)" +#: builtin/show-index.c msgid "hash-algorithm" msgstr "algorisme de resum" +#: builtin/show-index.c msgid "Unknown hash algorithm" msgstr "Algorisme de resum desconegut" +#: builtin/show-ref.c msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<patró>...]" +#: builtin/show-ref.c msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" " [-s | --hash[=<n>]] [--abbrev[=<n>]]\n" @@ -12091,49 +15428,63 @@ msgid "" msgstr "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" " [-s | --hash[=<n>]] [--abbrev[=<n>]]\n" -" [--] [<ref>...]" +" [--] [<referència>...]" +#: builtin/show-ref.c msgid "git show-ref --exclude-existing[=<pattern>]" msgstr "git show-ref --exclude-existing[=<patró>]" +#: builtin/show-ref.c msgid "git show-ref --exists <ref>" -msgstr "git show-ref --exists <ref>" +msgstr "git show-ref --exists <referència>" +#: builtin/show-ref.c msgid "reference does not exist" msgstr "la referència no existeix" +#: builtin/show-ref.c msgid "failed to look up reference" msgstr "s'ha produït en cercar la referència" -msgid "only show tags (can be combined with heads)" -msgstr "mostra només les etiquetes (es pot combinar amb heads)" +#: builtin/show-ref.c +msgid "only show tags (can be combined with --branches)" +msgstr "mostra només les etiquetes (es pot combinar amb --branches)" -msgid "only show heads (can be combined with tags)" -msgstr "mostra només els caps (es pot combinar amb tags)" +#: builtin/show-ref.c +msgid "only show branches (can be combined with --tags)" +msgstr "mostra només les branques (es pot combinar amb --tags)" +#: builtin/show-ref.c msgid "check for reference existence without resolving" msgstr "comprova l'existència de referència sense resoldre" +#: builtin/show-ref.c msgid "stricter reference checking, requires exact ref path" msgstr "" "comprovació de referència més estricta, requereix el camà de referència " "exacte" +#: builtin/show-ref.c msgid "show the HEAD reference, even if it would be filtered out" msgstr "mostra la referència HEAD, encara que es filtrés" +#: builtin/show-ref.c msgid "dereference tags into object IDs" msgstr "desreferencia les etiquetes a ID d'objecte" +#: builtin/show-ref.c msgid "only show SHA1 hash using <n> digits" msgstr "mostra el resum SHA1 usant només <n> xifres" +#: builtin/show-ref.c msgid "do not print results to stdout (useful with --verify)" msgstr "no imprimeixis els resultats a stdout (útil amb --verify)" +#: builtin/show-ref.c msgid "show refs from stdin that aren't in local repository" msgstr "mostra les referències de stdin que no siguin en el repositori local" +#: builtin/sparse-checkout.c msgid "" "git sparse-checkout (init | list | set | add | reapply | disable | check-" "rules) [<options>]" @@ -12141,14 +15492,17 @@ msgstr "" "git sparse-checkout (init | list | set | add | reapply | disable | check-" "rules) [<opcions>]" +#: builtin/sparse-checkout.c msgid "this worktree is not sparse" msgstr "aquest arbre de treball no és dispers" +#: builtin/sparse-checkout.c msgid "this worktree is not sparse (sparse-checkout file may not exist)" msgstr "" "aquest arbre de treball no és dispers (pot ser que el fitxer sparse-checkout " "no existeixi)" +#: builtin/sparse-checkout.c #, c-format msgid "" "directory '%s' contains untracked files, but is not in the sparse-checkout " @@ -12157,53 +15511,73 @@ msgstr "" "el directori «%s» conté fitxers no seguits, però no està en el con de sparse-" "checkout" +#: builtin/sparse-checkout.c #, c-format msgid "failed to remove directory '%s'" msgstr "s'ha produït un error en suprimir el directori «%s»" +#: builtin/sparse-checkout.c msgid "failed to create directory for sparse-checkout file" msgstr "no s'ha pogut crear el directori per al fitxer sparse-checkout" +#: builtin/sparse-checkout.c +#, c-format +msgid "unable to fdopen %s" +msgstr "no he pogut fer fdopen de «%s»" + +#: builtin/sparse-checkout.c msgid "failed to initialize worktree config" msgstr "no s'ha pogut inicialitzar la configuració de l'arbre de treball" +#: builtin/sparse-checkout.c msgid "failed to modify sparse-index config" msgstr "no s'ha pogut modificar la configuració de l'Ãndex dispers" +#: builtin/sparse-checkout.c msgid "initialize the sparse-checkout in cone mode" msgstr "inicialitza el «sparse-checkout» en mode con" +#: builtin/sparse-checkout.c msgid "toggle the use of a sparse index" msgstr "commuta l'ús d'un Ãndex dispers" +#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c #, c-format msgid "unable to create leading directories of %s" msgstr "no s'han pogut crear els directoris inicials de «%s»" +#: builtin/sparse-checkout.c #, c-format msgid "failed to open '%s'" msgstr "s'ha produït un error en obrir «%s»" +#: builtin/sparse-checkout.c #, c-format msgid "could not normalize path %s" msgstr "no s'ha pogut normalitzar el camà %s" +#: builtin/sparse-checkout.c #, c-format msgid "unable to unquote C-style string '%s'" msgstr "no s'han pogut treure les cometes a la cadena amb estil C «%s»" +#: builtin/sparse-checkout.c msgid "unable to load existing sparse-checkout patterns" msgstr "no s'han pogut carregar els patrons de «sparse-checkout» existents" +#: builtin/sparse-checkout.c msgid "existing sparse-checkout patterns do not use cone mode" msgstr "els patrons de «sparse-checkout» existents no usen el mode con" +#: builtin/sparse-checkout.c msgid "please run from the toplevel directory in non-cone mode" msgstr "executeu des del directori de nivell superior en mode que no sigui con" +#: builtin/sparse-checkout.c msgid "specify directories rather than patterns (no leading slash)" msgstr "especifica els directoris en lloc dels patrons (sense barra inclinada)" +#: builtin/sparse-checkout.c msgid "" "specify directories rather than patterns. If your directory starts with a " "'!', pass --skip-checks" @@ -12211,6 +15585,7 @@ msgstr "" "especifica els directoris en lloc dels patrons. Si el vostre directori " "comença amb un «!», passeu --skip-checks" +#: builtin/sparse-checkout.c msgid "" "specify directories rather than patterns. If your directory really has any " "of '*?[]\\' in it, pass --skip-checks" @@ -12218,6 +15593,7 @@ msgstr "" "especifica els directoris en lloc dels patrons. Si el vostre directori " "realment té alguna de «*?[]\\», useu --skip-checks" +#: builtin/sparse-checkout.c #, c-format msgid "" "'%s' is not a directory; to treat it as a directory anyway, rerun with --" @@ -12226,6 +15602,7 @@ msgstr "" "«%s» no és un directori; per a tractar-lo com un directori, torneu a " "executar amb --skip-checks" +#: builtin/sparse-checkout.c #, c-format msgid "" "pass a leading slash before paths such as '%s' if you want a single file " @@ -12234,35 +15611,43 @@ msgstr "" "passa una barra d'inici abans dels camins com ara «%s» si voleu un sol " "fitxer (vegeu «NON-CONE PROBLEMS» al manual de git-sparse-checkout)." +#: builtin/sparse-checkout.c msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)" -msgstr "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)" +msgstr "git sparse-checkout add [--skip-checks] (--stdin | <patrons>)" +#: builtin/sparse-checkout.c msgid "" "skip some sanity checks on the given paths that might give false positives" msgstr "" "omet alguns controls de sanitat en els camins donats que podrien donar " "falsos positius" +#: builtin/sparse-checkout.c msgid "read patterns from standard in" msgstr "llegeix els patrons de l'entrada està ndard" +#: builtin/sparse-checkout.c msgid "no sparse-checkout to add to" msgstr "no hi ha un sparse-checkout a afegir" +#: builtin/sparse-checkout.c msgid "" "git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] " "(--stdin | <patterns>)" msgstr "" "git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] " -"(--stdin | <patterns>)" +"(--stdin | <patrons>)" +#: builtin/sparse-checkout.c msgid "must be in a sparse-checkout to reapply sparsity patterns" msgstr "" "ha d'estar en un sparse-checkout per a tornar a aplicar patrons de dispersió" +#: builtin/sparse-checkout.c msgid "error while refreshing working directory" msgstr "s'ha produït un error en actualitzar el directori de treball" +#: builtin/sparse-checkout.c msgid "" "git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-" "file <file>]" @@ -12270,20 +15655,25 @@ msgstr "" "git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-" "file <fitxer>]" +#: builtin/sparse-checkout.c msgid "terminate input and output files by a NUL character" msgstr "acaba els fitxers d'entrada i de sortida amb un carà cter NUL" +#: builtin/sparse-checkout.c msgid "when used with --rules-file interpret patterns as cone mode patterns" msgstr "" "quan s'utilitza amb --rules-file, interpreta els patrons com a patrons del " "mode con" +#: builtin/sparse-checkout.c msgid "use patterns in <file> instead of the current ones." msgstr "utilitza patrons en <file> en lloc dels actuals." +#: builtin/stash.c msgid "git stash list [<log-options>]" -msgstr "git stash list [<log-options>]" +msgstr "git stash list [<opcions-registre>]" +#: builtin/stash.c msgid "" "git stash show [-u | --include-untracked | --only-untracked] [<diff-" "options>] [<stash>]" @@ -12291,22 +15681,28 @@ msgstr "" "git stash show [-u | --include-untracked | --only-untracked] [<diff-" "options>] [<stash>]" +#: builtin/stash.c msgid "git stash drop [-q | --quiet] [<stash>]" msgstr "git stash drop [-q | --quiet] [<stash>]" +#: builtin/stash.c msgid "git stash pop [--index] [-q | --quiet] [<stash>]" msgstr "git stash pop [--index] [-q | --quiet] [<stash>]" +#: builtin/stash.c msgid "git stash apply [--index] [-q | --quiet] [<stash>]" msgstr "git stash apply [--index] [-q | --quiet] [<stash>]" +#: builtin/stash.c msgid "git stash branch <branchname> [<stash>]" msgstr "git stash branch <nom-de-branca> [<stash>]" +#: builtin/stash.c msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>" msgstr "" "git stash store [(-m | --message) <missatge>] [-q | --quiet] <comissió>" +#: builtin/stash.c msgid "" "git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q " "| --quiet]\n" @@ -12322,6 +15718,7 @@ msgstr "" " [--pathspec-from-file=<fitxer> [--pathspec-file-nul]]\n" " [--] [<pathspec>...]]" +#: builtin/stash.c msgid "" "git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | " "--quiet]\n" @@ -12331,27 +15728,34 @@ msgstr "" "--quiet]\n" " [-u | --include-untracked] [-a | --all] [<missatge>]" +#: builtin/stash.c msgid "git stash create [<message>]" msgstr "git stash create [<missatge>]" +#: builtin/stash.c #, c-format msgid "'%s' is not a stash-like commit" msgstr "«%s» no és una comissió de tipus «stash»" +#: builtin/stash.c #, c-format msgid "Too many revisions specified:%s" msgstr "S'han especificat massa revisions:%s" +#: builtin/stash.c msgid "No stash entries found." msgstr "No s'ha trobat cap entrada «stash»." +#: builtin/stash.c #, c-format msgid "%s is not a valid reference" msgstr "«%s» no és una referència và lida" +#: builtin/stash.c msgid "git stash clear with arguments is unimplemented" msgstr "git stash clear amb parà metres no està implementat" +#: builtin/stash.c #, c-format msgid "" "WARNING: Untracked file in way of tracked file! Renaming\n" @@ -12362,154 +15766,202 @@ msgstr "" " %s -> %s\n" " per a fer-ne espai.\n" +#: builtin/stash.c msgid "cannot apply a stash in the middle of a merge" msgstr "no es pot aplicar un «stash» enmig d'una fusió" +#: builtin/stash.c #, c-format msgid "could not generate diff %s^!." msgstr "no s'ha pogut generar diff %s^!." +#: builtin/stash.c msgid "conflicts in index. Try without --index." msgstr "hi ha conflictes en l'Ãndex. Proveu-ho sense --index." +#: builtin/stash.c msgid "could not save index tree" msgstr "no s'ha pogut desar l'arbre d'Ãndex" +#: builtin/stash.c #, c-format msgid "Merging %s with %s" msgstr "S'està fusionant %s amb %s" +#: builtin/stash.c msgid "Index was not unstashed." msgstr "L'Ãndex no estava «unstashed»." +#: builtin/stash.c msgid "could not restore untracked files from stash" msgstr "no s'han pogut restaurar els fitxers no seguits des del «stash»" +#: builtin/stash.c msgid "attempt to recreate the index" msgstr "intenta tornar a crear l'Ãndex" +#: builtin/stash.c #, c-format msgid "Dropped %s (%s)" msgstr "Descartada %s (%s)" +#: builtin/stash.c #, c-format msgid "%s: Could not drop stash entry" msgstr "%s: no s'ha pogut descartar l'entrada «stash»" +#: builtin/stash.c #, c-format msgid "'%s' is not a stash reference" msgstr "«%s» no és una referència «stash»" +#: builtin/stash.c msgid "The stash entry is kept in case you need it again." -msgstr "Es conserva l'entrada «stash» en cas que la necessiteu altra vegada." +msgstr "" +"Es conserva l'entrada «stash» en cas que la necessiteu una altra vegada." +#: builtin/stash.c msgid "No branch name specified" msgstr "Cap nom de branca especificat" +#: builtin/stash.c msgid "failed to parse tree" msgstr "s'ha produït un error en analitzar l'arbre" +#: builtin/stash.c msgid "failed to unpack trees" msgstr "s'ha produït un error en desempaquetar els arbres" +#: builtin/stash.c msgid "include untracked files in the stash" msgstr "inclou els fitxers no seguits a «stash»" +#: builtin/stash.c msgid "only show untracked files in the stash" msgstr "mostra només els fitxers no seguits a «stash»" +#: builtin/stash.c #, c-format msgid "Cannot update %s with %s" msgstr "No es pot actualitzar %s amb %s" +#: builtin/stash.c msgid "stash message" msgstr "missatge «stash»" +#: builtin/stash.c msgid "\"git stash store\" requires one <commit> argument" msgstr "«git stash store» requereix un argument <comissió>" +#: builtin/stash.c msgid "No staged changes" msgstr "No hi ha canvis a «stage»" +#: builtin/stash.c msgid "No changes selected" msgstr "No hi ha canvis seleccionats" +#: builtin/stash.c msgid "You do not have the initial commit yet" msgstr "Encara no teniu la comissió inicial" +#: builtin/stash.c msgid "Cannot save the current index state" msgstr "No es pot desar l'estat d'Ãndex actual" +#: builtin/stash.c msgid "Cannot save the untracked files" msgstr "No es poden desar els fitxers no seguits" +#: builtin/stash.c msgid "Cannot save the current worktree state" msgstr "No es pot desar l'estat d'arbre de treball actual" +#: builtin/stash.c msgid "Cannot save the current staged state" msgstr "No es pot desar l'estat «stage» actual" +#: builtin/stash.c msgid "Cannot record working tree state" msgstr "No es pot registrar l'estat de l'arbre de treball" +#: builtin/stash.c msgid "Can't use --patch and --include-untracked or --all at the same time" msgstr "No es poden usar --patch i --include-untracked o --all a la vegada" +#: builtin/stash.c msgid "Can't use --staged and --include-untracked or --all at the same time" msgstr "No es poden usar --staged i --include-untracked o --all a la vegada" +#: builtin/stash.c msgid "Did you forget to 'git add'?" msgstr "Heu oblidat de fer «git add»?" +#: builtin/stash.c msgid "No local changes to save" msgstr "No hi ha canvis locals a desar" +#: builtin/stash.c msgid "Cannot initialize stash" msgstr "No es pot inicialitzar el magatzem" +#: builtin/stash.c msgid "Cannot save the current status" msgstr "No es pot desar l'estat actual" +#: builtin/stash.c #, c-format msgid "Saved working directory and index state %s" msgstr "S'han desat el directori de treball i l'estat d'Ãndex %s" +#: builtin/stash.c msgid "Cannot remove worktree changes" msgstr "No es poden eliminar els canvis de l'arbre de treball" +#: builtin/stash.c msgid "keep index" msgstr "mantén l'Ãndex" +#: builtin/stash.c msgid "stash staged changes only" msgstr "fes «stash» només dels canvis «staged»" +#: builtin/stash.c msgid "stash in patch mode" msgstr "fes «stash» en mode pedaç" +#: builtin/stash.c msgid "quiet mode" msgstr "mode silenciós" +#: builtin/stash.c msgid "include untracked files in stash" msgstr "inclou els fitxers no seguits a «stash»" +#: builtin/stash.c msgid "include ignore files" msgstr "inclou els fitxers ignorats" +#: builtin/stripspace.c msgid "skip and remove all lines starting with comment character" msgstr "" "omet i elimina totes les lÃnies que comencin amb el carà cter de comentari" +#: builtin/stripspace.c msgid "prepend comment character and space to each line" msgstr "anteposa el carà cter de comentari i un espai a cada lÃnia" +#: builtin/submodule--helper.c #, c-format msgid "Expecting a full ref name, got %s" msgstr "S'espera un nom de referència ple, s'ha rebut %s" +#: builtin/submodule--helper.c #, c-format msgid "could not get a repository handle for submodule '%s'" msgstr "no s'ha pogut obtenir el gestor del repositori pel submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "" "could not look up configuration '%s'. Assuming this repository is its own " @@ -12518,14 +15970,17 @@ msgstr "" "no s'ha pogut trobar la configuració «%s». S'assumeix que aquest repositori " "és el seu repositori font autoritzat." +#: builtin/submodule--helper.c #, c-format msgid "No url found for submodule path '%s' in .gitmodules" msgstr "No s'ha trobat cap url per al camà de submòdul «%s» a .gitmodules" +#: builtin/submodule--helper.c #, c-format msgid "Entering '%s'\n" msgstr "S'està entrant a «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "" "run_command returned non-zero status for %s\n" @@ -12534,6 +15989,7 @@ msgstr "" "run_command ha retornat un estat diferent de zero per a %s\n" "." +#: builtin/submodule--helper.c #, c-format msgid "" "run_command returned non-zero status while recursing in the nested " @@ -12544,56 +16000,70 @@ msgstr "" "recursivament als submòduls imbricats de %s\n" "." +#: builtin/submodule--helper.c msgid "suppress output of entering each submodule command" msgstr "omet la sortida en entrar a cada ordre del submòdul" +#: builtin/submodule--helper.c msgid "recurse into nested submodules" msgstr "cerca recursivament als submòduls imbricats" +#: builtin/submodule--helper.c msgid "git submodule foreach [--quiet] [--recursive] [--] <command>" msgstr "git submodule foreach [--quiet] [--recursive] [--] <ordre>" +#: builtin/submodule--helper.c #, c-format msgid "Failed to register url for submodule path '%s'" msgstr "S'ha produït un error en registrar l'url per al camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Submodule '%s' (%s) registered for path '%s'\n" msgstr "S'ha registrat el submòdul «%s» (%s) per al camà «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "warning: command update mode suggested for submodule '%s'\n" msgstr "" "advertència: se suggereix el mode d'actualització per ordre per al submòdul " "«%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "Failed to register update mode for submodule path '%s'" msgstr "" "S'ha produït un error en registrar el mode d'actualització per al camà de " "submòdul «%s»" +#: builtin/submodule--helper.c msgid "suppress output for initializing a submodule" msgstr "omet la sortida en inicialitzar un submòdul" +#: builtin/submodule--helper.c msgid "git submodule init [<options>] [<path>]" msgstr "git submodule init [<opcions>] [<camÃ>]" +#: builtin/submodule--helper.c #, c-format msgid "no submodule mapping found in .gitmodules for path '%s'" msgstr "no s'ha trobat cap mapatge de submòdul a .gitmodules per al camà «%s»" +#: builtin/submodule--helper.c #, c-format msgid "could not resolve HEAD ref inside the submodule '%s'" msgstr "no s'ha pogut resoldre la referència a HEAD dins del submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "failed to recurse into submodule '%s'" msgstr "s'ha produït un error en cercar recursivament al submòdul «%s»" +#: builtin/submodule--helper.c msgid "suppress submodule status output" msgstr "suprimeix la sortida de l'estat del submòdul" +#: builtin/submodule--helper.c msgid "" "use commit stored in the index instead of the one stored in the submodule " "HEAD" @@ -12601,69 +16071,87 @@ msgstr "" "utilitza la comissió emmagatzemada a l'Ãndex en lloc de l'emmagatzemada al " "HEAD del submòdul" +#: builtin/submodule--helper.c msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]" msgstr "git submodule status [--quiet] [--cached] [--recursive] [<camÃ>...]" +#: builtin/submodule--helper.c #, c-format msgid "* %s %s(blob)->%s(submodule)" msgstr "* %s %s(blob)->%s(submòdul)" +#: builtin/submodule--helper.c #, c-format msgid "* %s %s(submodule)->%s(blob)" msgstr "* %s %s(submòdul)->%s(blob)" +#: builtin/submodule--helper.c #, c-format msgid "%s" msgstr "%s" +#: builtin/submodule--helper.c #, c-format msgid "couldn't hash object from '%s'" msgstr "no s'ha pogut fer el resum de l'objecte de «%s»" +#: builtin/submodule--helper.c #, c-format -msgid "unexpected mode %o\n" -msgstr "mode inesperat %o\n" +msgid "unexpected mode %o" +msgstr "mode %o inesperat" +#: builtin/submodule--helper.c msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "" "utilitza la comissió emmagatzemada a l'Ãndex en lloc de l'emmagatzemada al " "HEAD del submòdul" +#: builtin/submodule--helper.c msgid "compare the commit in the index with that in the submodule HEAD" msgstr "" "compara la comissió emmagatzemada a l'Ãndex en lloc de l'emmagatzemada al " "HEAD del submòdul" +#: builtin/submodule--helper.c msgid "skip submodules with 'ignore_config' value set to 'all'" msgstr "omet els submòduls amb el valor «ignore_config» establert a «all»" +#: builtin/submodule--helper.c msgid "limit the summary size" msgstr "limita la mida del resum" +#: builtin/submodule--helper.c msgid "git submodule summary [<options>] [<commit>] [--] [<path>]" msgstr "git submodule summary [<opcions>] [<comissió>] [--] [<camÃ>]" +#: builtin/submodule--helper.c msgid "could not fetch a revision for HEAD" msgstr "no s'ha pogut obtenir una revisió per a HEAD" +#: builtin/submodule--helper.c #, c-format msgid "Synchronizing submodule url for '%s'\n" msgstr "S'està sincronitzant l'url del submòdul per a «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "failed to register url for submodule path '%s'" msgstr "s'ha produït un error en registrar l'url per al camà del submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "failed to update remote for submodule '%s'" msgstr "s'ha produït un error en actualitzar el remot pel submòdul «%s»" +#: builtin/submodule--helper.c msgid "suppress output of synchronizing submodule url" msgstr "omet la sortida de la sincronització de l'URL del submòdul" +#: builtin/submodule--helper.c msgid "git submodule sync [--quiet] [--recursive] [<path>]" msgstr "git submodule sync [--quiet] [--recursive] [<camÃ>]" +#: builtin/submodule--helper.c #, c-format msgid "" "Submodule work tree '%s' contains a .git directory. This will be replaced " @@ -12672,6 +16160,7 @@ msgstr "" "L'arbre de treball del submòdul «%s» conté un directori .git. Aquest es " "reemplaçarà amb un fitxer a .git mitjançant l'ús d'«absorbgitdirs»." +#: builtin/submodule--helper.c #, c-format msgid "" "Submodule work tree '%s' contains local modifications; use '-f' to discard " @@ -12680,38 +16169,47 @@ msgstr "" "L'arbre de treball del submòdul «%s» conté modificacions locals; useu «-f» " "per a descartar-les" +#: builtin/submodule--helper.c #, c-format msgid "Cleared directory '%s'\n" msgstr "S'ha esborrat el directori «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "Could not remove submodule work tree '%s'\n" msgstr "No s'ha pogut eliminar l'arbre de treball de submòdul «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "could not create empty submodule directory %s" msgstr "no s'ha pogut crear el directori de submòdul buit %s" +#: builtin/submodule--helper.c #, c-format msgid "Submodule '%s' (%s) unregistered for path '%s'\n" msgstr "S'ha desregistrat el submòdul «%s» (%s) per al camà «%s»\n" +#: builtin/submodule--helper.c msgid "remove submodule working trees even if they contain local changes" msgstr "" "elimina els arbres de treball dels submòduls fins i tot si contenen canvis " "locals" +#: builtin/submodule--helper.c msgid "unregister all submodules" msgstr "desregistra tots els submòduls" +#: builtin/submodule--helper.c msgid "" "git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]" msgstr "" "git submodule deinit [--quiet] [-f | --force] [--all | [--] [<camÃ>...]]" +#: builtin/submodule--helper.c msgid "Use '--all' if you really want to deinitialize all submodules" msgstr "Useu «--all» si realment voleu desinicialitzar tots els submòduls" +#: builtin/submodule--helper.c msgid "" "An alternate computed from a superproject's alternate is invalid.\n" "To allow Git to clone without an alternate in such a case, set\n" @@ -12724,138 +16222,172 @@ msgstr "" "submodule.alternateErrorStrategy a «info» o bé cloneu amb\n" "«--reference-if-able' en comptes de «--reference»." +#: builtin/submodule--helper.c #, c-format msgid "could not get a repository handle for gitdir '%s'" msgstr "no s'ha pogut obtenir el gestor del repositori per al gitdir «%s»" +#: builtin/submodule--helper.c #, c-format msgid "submodule '%s' cannot add alternate: %s" msgstr "el submòdul «%s» no pot afegir un alternatiu: %s" +#: builtin/submodule--helper.c #, c-format msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized" msgstr "No es reconeix el valor «%s» per a submodule.alternateErrorStrategy" +#: builtin/submodule--helper.c #, c-format msgid "Value '%s' for submodule.alternateLocation is not recognized" msgstr "No es reconeix el valor «%s» per a submodule.alternateLocation" +#: builtin/submodule--helper.c submodule.c #, c-format msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "s'ha rebutjat crear/usar «%s» en el directori git d'un altre submòdul" -#, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "el clonatge de «%s» al camà de submòdul «%s» ha fallat" - +#: builtin/submodule--helper.c #, c-format msgid "directory not empty: '%s'" msgstr "directori no buit: «%s»" +#: builtin/submodule--helper.c +#, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "el clonatge de «%s» al camà de submòdul «%s» ha fallat" + +#: builtin/submodule--helper.c #, c-format msgid "could not get submodule directory for '%s'" msgstr "no s'ha pogut obtenir el directori de submòdul per a «%s»" +#: builtin/submodule--helper.c msgid "alternative anchor for relative paths" msgstr "à ncora alternativa per als camins relatius" +#: builtin/submodule--helper.c msgid "where the new submodule will be cloned to" msgstr "a on es clonarà el submòdul nou" +#: builtin/submodule--helper.c msgid "name of the new submodule" msgstr "nom del submòdul nou" +#: builtin/submodule--helper.c msgid "url where to clone the submodule from" msgstr "url del qual clonar el submòdul" +#: builtin/submodule--helper.c msgid "depth for shallow clones" msgstr "profunditat dels clons superficials" +#: builtin/submodule--helper.c msgid "force cloning progress" msgstr "força el progrés del clonatge" +#: builtin/submodule--helper.c msgid "disallow cloning into non-empty directory" msgstr "no permetis clonar en un directori no buit" +#: builtin/submodule--helper.c msgid "" "git submodule--helper clone [--prefix=<path>] [--quiet] [--reference " "<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter " "<filter-spec>] --url <url> --path <path>" msgstr "" "git submodule--helper clone [--prefix=<camÃ>] [--quiet] [--reference " -"<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter " +"<repositori>] [--name <nom>] [--depth <depth>] [--single-branch] [--filter " "<filter-spec>] --url <url> --path <camÃ>" +#: builtin/submodule--helper.c #, c-format msgid "Invalid update mode '%s' configured for submodule path '%s'" msgstr "" "Mode d'actualització «%s» configurat no và lid per al camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Submodule path '%s' not initialized" msgstr "El camà de submòdul «%s» no està inicialitzat" +#: builtin/submodule--helper.c msgid "Maybe you want to use 'update --init'?" msgstr "Potser voleu usar «update --init»?" +#: builtin/submodule--helper.c #, c-format msgid "Skipping unmerged submodule %s" msgstr "S'està ometent el submòdul no fusionat %s" +#: builtin/submodule--helper.c #, c-format msgid "Skipping submodule '%s'" msgstr "S'està ometent el submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "cannot clone submodule '%s' without a URL" msgstr "no es pot clonar el submòdul «%s» sense un URL" +#: builtin/submodule--helper.c #, c-format msgid "Failed to clone '%s'. Retry scheduled" msgstr "S'ha produït un error en clonar «%s». S'ha programat un reintent" +#: builtin/submodule--helper.c #, c-format msgid "Failed to clone '%s' a second time, aborting" msgstr "S'ha produït un error per segon cop en clonar «%s», s'està avortant" +#: builtin/submodule--helper.c #, c-format msgid "Unable to checkout '%s' in submodule path '%s'" msgstr "No s'ha pogut agafar «%s» en el camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Unable to rebase '%s' in submodule path '%s'" msgstr "No s'ha pogut fer «rebase» «%s» en el camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Unable to merge '%s' in submodule path '%s'" msgstr "No s'ha pogut fusionar «%s» en el camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Execution of '%s %s' failed in submodule path '%s'" msgstr "L'execució de «%s %s» ha fallat en el camà de submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Submodule path '%s': checked out '%s'\n" msgstr "Camà de submòdul «%s»: s'ha agafat «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "Submodule path '%s': rebased into '%s'\n" msgstr "Camà de submòdul «%s»: s'ha fet «rebase» en «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "Submodule path '%s': merged in '%s'\n" msgstr "Camà de submòdul «%s»: s'ha fusionat en «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "Submodule path '%s': '%s %s'\n" msgstr "El camà de submòdul «%s»: '%s %s'\n" +#: builtin/submodule--helper.c #, c-format msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:" msgstr "" "No s'ha pogut obtenir en el camà de submòdul «$%s»; s'està intentant obtenir " "directament %s:" +#: builtin/submodule--helper.c #, c-format msgid "" "Fetched in submodule path '%s', but it did not contain %s. Direct fetching " @@ -12864,10 +16396,12 @@ msgstr "" "S'ha obtingut en un camà de submòdul «%s», però no contenia %s. L'obtenció " "directa d'aquesta comissió ha fallat." +#: builtin/submodule--helper.c #, c-format msgid "could not initialize submodule at path '%s'" msgstr "no s'ha pogut inicialitzar el submòdul al camà «%s»" +#: builtin/submodule--helper.c #, c-format msgid "" "Submodule (%s) branch configured to inherit branch from superproject, but " @@ -12876,62 +16410,80 @@ msgstr "" "La branca de submòdul (%s) està configurada per a heretar la branca del " "superprojecte, però el superprojecte no és en cap branca" +#: builtin/submodule--helper.c #, c-format msgid "Unable to find current revision in submodule path '%s'" msgstr "No s'ha pogut trobar la revisió actual al camà del submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Unable to fetch in submodule path '%s'" msgstr "No s'ha pogut obtenir el camà del submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Unable to find %s revision in submodule path '%s'" msgstr "No s'ha pogut trobar la revisió %s en el camà del submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Failed to recurse into submodule path '%s'" msgstr "" "s'ha produït un error en cercar recursivament al camà del submòdul «%s»" +#: builtin/submodule--helper.c msgid "force checkout updates" msgstr "força les actualitzacions" +#: builtin/submodule--helper.c msgid "initialize uninitialized submodules before update" msgstr "inicialitza els submòduls sense inicialitzar abans d'actualitzar" +#: builtin/submodule--helper.c msgid "use SHA-1 of submodule's remote tracking branch" msgstr "usa el SHA-1 de la branca de seguiment remota del submòdul" +#: builtin/submodule--helper.c msgid "traverse submodules recursively" msgstr "recorre els submòduls recursivament" +#: builtin/submodule--helper.c msgid "don't fetch new objects from the remote site" msgstr "no obtinguis els objectes nous del lloc remot" +#: builtin/submodule--helper.c msgid "use the 'checkout' update strategy (default)" msgstr "utilitza l'estratègia d'actualització «checkout» (predeterminada)" +#: builtin/submodule--helper.c msgid "use the 'merge' update strategy" msgstr "utilitza l'estratègia d'actualització de «merge»" +#: builtin/submodule--helper.c msgid "use the 'rebase' update strategy" msgstr "utilitza l'estratègia d'actualització de «rebase»" +#: builtin/submodule--helper.c msgid "create a shallow clone truncated to the specified number of revisions" msgstr "crea un clon superficial truncat al nombre de revisions especificat" +#: builtin/submodule--helper.c msgid "parallel jobs" msgstr "tasques paral·leles" +#: builtin/submodule--helper.c msgid "whether the initial clone should follow the shallow recommendation" msgstr "si el clonatge inicial ha de seguir la recomanació de superficialitat" +#: builtin/submodule--helper.c msgid "don't print cloning progress" msgstr "no imprimeixis el progrés del clonatge" +#: builtin/submodule--helper.c msgid "disallow cloning into non-empty directory, implies --init" msgstr "no permetis clonar en un directori no buit, implica --init" +#: builtin/submodule--helper.c msgid "" "git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] " "[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-" @@ -12940,68 +16492,86 @@ msgid "" msgstr "" "git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] " "[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-" -"shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] " +"shallow] [--reference <repositori>] [--recursive] [--[no-]single-branch] " "[--] [<camÃ>...]" +#: builtin/submodule--helper.c submodule.c msgid "Failed to resolve HEAD as a valid ref." msgstr "S'ha produït un error en resoldre HEAD com a referència và lida." +#: builtin/submodule--helper.c msgid "git submodule absorbgitdirs [<options>] [<path>...]" msgstr "git submodule absorbgitdirs [<opcions>] [<camÃ>...]" +#: builtin/submodule--helper.c msgid "suppress output for setting url of a submodule" msgstr "omet la sortida en configurar un URL d'un submòdul" +#: builtin/submodule--helper.c msgid "git submodule set-url [--quiet] <path> <newurl>" -msgstr "git submodule set-url [--quiet] <camÃ> <newurl>" +msgstr "git submodule set-url [--quiet] <camÃ> <url-nou>" +#: builtin/submodule--helper.c msgid "set the default tracking branch to master" msgstr "estableix la branca de seguiment per defecte a «master»" +#: builtin/submodule--helper.c msgid "set the default tracking branch" msgstr "estableix la branca de seguiment per defecte" +#: builtin/submodule--helper.c msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>" msgstr "git submodule set-branch [-q|--quiet] (-d|--default) <camÃ>" +#: builtin/submodule--helper.c msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>" msgstr "git submodule set-branch [-q|--quiet] (-b|--branch) <branca> <camÃ>" +#: builtin/submodule--helper.c msgid "--branch or --default required" msgstr "cal --branch o --default" +#: builtin/submodule--helper.c msgid "print only error messages" msgstr "mostra només els missatges d'error" +#: builtin/submodule--helper.c msgid "force creation" msgstr "força la creació" +#: builtin/submodule--helper.c msgid "show whether the branch would be created" msgstr "mostra si es crearà la branca" +#: builtin/submodule--helper.c msgid "" "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" "quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" msgstr "" "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" -"quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" +"quiet] [-t|--track] [-n|--dry-run] <nom> <oid-inicial> <nom-inicial>" +#: builtin/submodule--helper.c #, c-format msgid "creating branch '%s'" msgstr "s'està creant la branca «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Adding existing repo at '%s' to the index\n" msgstr "S'està afegint el repositori existent a «%s» a l'Ãndex\n" +#: builtin/submodule--helper.c #, c-format msgid "'%s' already exists and is not a valid git repo" msgstr "«%s» ja existeix i no és un repositori de git và lid" +#: builtin/submodule--helper.c #, c-format msgid "A git directory for '%s' is found locally with remote(s):\n" msgstr "S'ha trobat un directori de git per a «%s» localment amb els remots:\n" +#: builtin/submodule--helper.c #, c-format msgid "" "If you want to reuse this local git directory instead of cloning again from\n" @@ -13019,46 +16589,58 @@ msgstr "" "o no esteu segur de què vol dir això, trieu un altre nom amb l'opció «--" "name»." +#: builtin/submodule--helper.c #, c-format msgid "Reactivating local git directory for submodule '%s'\n" msgstr "S'està reactivant el directori de git local per al submòdul «%s»\n" +#: builtin/submodule--helper.c #, c-format msgid "unable to checkout submodule '%s'" msgstr "no s'ha pogut agafar el submòdul «%s»" +#: builtin/submodule--helper.c msgid "please make sure that the .gitmodules file is in the working tree" msgstr "assegureu-vos que el fitxer .gitmodules és a l'arbre de treball" +#: builtin/submodule--helper.c #, c-format msgid "Failed to add submodule '%s'" msgstr "S'ha produït un error en afegir el submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "Failed to register submodule '%s'" msgstr "S'ha produït un error en registrar el submòdul «%s»" +#: builtin/submodule--helper.c #, c-format msgid "'%s' already exists in the index" msgstr "«%s» ja existeix en l'Ãndex" +#: builtin/submodule--helper.c #, c-format msgid "'%s' already exists in the index and is not a submodule" msgstr "«%s» ja existeix en l'Ãndex i no és submòdul" +#: builtin/submodule--helper.c read-cache.c #, c-format msgid "'%s' does not have a commit checked out" msgstr "«%s» no té una comissió comprovada" +#: builtin/submodule--helper.c msgid "branch of repository to add as submodule" msgstr "la branca del repositori a afegir com a submòdul" +#: builtin/submodule--helper.c msgid "allow adding an otherwise ignored submodule path" msgstr "permet afegir un camà de submòdul que si no s'hagués ignorat" +#: builtin/submodule--helper.c msgid "borrow the objects from reference repositories" msgstr "manlleva els objectes dels repositoris de referències" +#: builtin/submodule--helper.c msgid "" "sets the submodule's name to the given string instead of defaulting to its " "path" @@ -13066,62 +16648,81 @@ msgstr "" "estableix el nom del submòdul a la cadena donada en lloc de per defecte al " "seu camÃ" +#: builtin/submodule--helper.c msgid "git submodule add [<options>] [--] <repository> [<path>]" -msgstr "git submodule add [<opcions>] [--] <repository> [<camÃ>]" +msgstr "git submodule add [<opcions>] [--] <repositori> [<camÃ>]" +#: builtin/submodule--helper.c msgid "Relative path can only be used from the toplevel of the working tree" msgstr "" "El camà relatiu només es pot usar des del nivell superior de l'arbre de " "treball" +#: builtin/submodule--helper.c #, c-format msgid "repo URL: '%s' must be absolute or begin with ./|../" msgstr "URL de repositori: «%s» ha de ser absolut o començar amb ./|../" +#: builtin/submodule--helper.c #, c-format msgid "'%s' is not a valid submodule name" msgstr "«%s» no és un nom de submòdul và lid" +#: builtin/submodule--helper.c msgid "git submodule--helper <command>" -msgstr "git submodule--helper <command>" +msgstr "git submodule--helper <ordre>" +#: builtin/symbolic-ref.c msgid "git symbolic-ref [-m <reason>] <name> <ref>" -msgstr "git symbolic-ref [-m <reason>] <name> <ref>" +msgstr "git symbolic-ref [-m <raó>] <nom> <referència>" +#: builtin/symbolic-ref.c msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>" -msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <name>" +msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <nom>" +#: builtin/symbolic-ref.c msgid "git symbolic-ref --delete [-q] <name>" -msgstr "git symbolic-ref --delete [-q] <name>" +msgstr "git symbolic-ref --delete [-q] <nom>" +#: builtin/symbolic-ref.c msgid "suppress error message for non-symbolic (detached) refs" msgstr "omet el missatge d'error de referències no simbòliques (separades)" +#: builtin/symbolic-ref.c msgid "delete symbolic ref" msgstr "suprimeix la referència simbòlica" +#: builtin/symbolic-ref.c msgid "shorten ref output" msgstr "escurça la sortida de referències" +#: builtin/symbolic-ref.c msgid "recursively dereference (default)" msgstr "desreferencia recursivament (per defecte)" +#: builtin/symbolic-ref.c builtin/update-ref.c msgid "reason" msgstr "raó" +#: builtin/symbolic-ref.c builtin/update-ref.c msgid "reason of the update" msgstr "raó de l'actualització" +#: builtin/tag.c msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" -"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <fitxer>] [-e]\n" -" <tagname> [<comissió> | <objecte>]" +"git tag [-a | -s | -u <id-clau>] [-f] [-m <missatge> | -F <fitxer>] [-e]\n" +" [(--trailer <token>[(=|:)<valor>])...]\n" +" <nom-etiqueta> [<comissió> | <objecte>]" +#: builtin/tag.c msgid "git tag -d <tagname>..." -msgstr "git tag -d <nom-d'etiqueta>..." +msgstr "git tag -d <nom-etiqueta>..." +#: builtin/tag.c msgid "" "git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n" " [--points-at <object>] [--column[=<options>] | --no-column]\n" @@ -13130,49 +16731,56 @@ msgid "" msgstr "" "git tag [-n[<num>]] -l [--contains <comissió>] [--no-contains <comissió>]\n" " [--points-at <objecte>] [--column[=<opcions>] | --no-column]\n" -" [--create-reflog] [--sort=<key>] [--format=<format>]\n" +" [--create-reflog] [--sort=<clau>] [--format=<format>]\n" " [--merged <comissió>] [--no-merged <comissió>] [<patró>...]" +#: builtin/tag.c msgid "git tag -v [--format=<format>] <tagname>..." -msgstr "git tag -v [--format=<format>] <nom-d'etiqueta>..." +msgstr "git tag -v [--format=<format>] <nom-etiqueta>..." +#: builtin/tag.c #, c-format msgid "tag '%s' not found." msgstr "no s'ha trobat l'etiqueta «%s»." +#: builtin/tag.c #, c-format msgid "Deleted tag '%s' (was %s)\n" msgstr "S'ha suprimit l'etiqueta «%s» (era %s)\n" +#: builtin/tag.c #, c-format msgid "" "\n" "Write a message for tag:\n" " %s\n" -"Lines starting with '%c' will be ignored.\n" +"Lines starting with '%s' will be ignored.\n" msgstr "" "\n" -"Escriviu el missatge de l'etiqueta:\n" +"Escriviu un missatge per a l'etiqueta:\n" " %s\n" -"Les lÃnies que comencin amb «%c» s'ignoraran.\n" +"S'ignoraran les lÃnies que comencen amb «%s».\n" +#: builtin/tag.c #, c-format msgid "" "\n" "Write a message for tag:\n" " %s\n" -"Lines starting with '%c' will be kept; you may remove them yourself if you " +"Lines starting with '%s' will be kept; you may remove them yourself if you " "want to.\n" msgstr "" "\n" -"Escriviu el missatge de l'etiqueta:\n" +"Escriviu un missatge per a l'etiqueta:\n" " %s\n" -"Les lÃnies que comencin amb «%c» es retindran; podeu eliminar-les per vós " -"mateix si voleu.\n" +"Es mantindran les lÃnies que comencin amb «%s»; les podeu eliminar si " +"voleu.\n" +#: builtin/tag.c msgid "unable to sign the tag" msgstr "no s'ha pogut signar l'etiqueta" +#: builtin/tag.c #, c-format msgid "" "You have created a nested tag. The object referred to by your new tag is\n" @@ -13186,275 +16794,361 @@ msgstr "" "\n" "\tgit tag -f %s %s^{}" +#: builtin/tag.c msgid "bad object type." msgstr "el tipus d'objecte és incorrecte." +#: builtin/tag.c msgid "no tag message?" msgstr "no hi ha cap missatge d'etiqueta?" +#: builtin/tag.c #, c-format msgid "The tag message has been left in %s\n" msgstr "S'ha deixat el missatge de l'etiqueta en %s\n" +#: builtin/tag.c msgid "list tag names" msgstr "llista els noms d'etiqueta" +#: builtin/tag.c msgid "print <n> lines of each tag message" msgstr "imprimeix <n> lÃnies de cada missatge d'etiqueta" +#: builtin/tag.c msgid "delete tags" msgstr "suprimeix les etiquetes" +#: builtin/tag.c msgid "verify tags" msgstr "verifica les etiquetes" +#: builtin/tag.c msgid "Tag creation options" msgstr "Opcions de creació d'etiquetes" +#: builtin/tag.c msgid "annotated tag, needs a message" msgstr "etiqueta anotada, necessita un missatge" +#: builtin/tag.c msgid "tag message" msgstr "missatge d'etiqueta" +#: builtin/tag.c msgid "force edit of tag message" msgstr "força l'edició del missatge de l'etiqueta" +#: builtin/tag.c msgid "annotated and GPG-signed tag" msgstr "etiqueta anotada i signada per GPG" +#: builtin/tag.c msgid "use another key to sign the tag" msgstr "usa una altra clau per a signar l'etiqueta" +#: builtin/tag.c msgid "replace the tag if exists" msgstr "reemplaça l'etiqueta si existeix" +#: builtin/tag.c builtin/update-ref.c msgid "create a reflog" msgstr "crea un registre de referències" +#: builtin/tag.c msgid "Tag listing options" msgstr "Opcions de llistat d'etiquetes" +#: builtin/tag.c msgid "show tag list in columns" msgstr "mostra la llista d'etiquetes en columnes" +#: builtin/tag.c msgid "print only tags that contain the commit" msgstr "imprimeix només les etiquetes que continguin la comissió" +#: builtin/tag.c msgid "print only tags that don't contain the commit" msgstr "imprimeix només les etiquetes que no continguin la comissió" +#: builtin/tag.c msgid "print only tags that are merged" msgstr "imprimeix només les etiquetes que s'han fusionat" +#: builtin/tag.c msgid "print only tags that are not merged" msgstr "imprimeix només les etiquetes que no s'han fusionat" +#: builtin/tag.c msgid "print only tags of the object" msgstr "imprimeix només les etiquetes de l'objecte" +#: builtin/tag.c +msgid "could not start 'git column'" +msgstr "no s'ha pogut iniciar «git column»" + +#: builtin/tag.c #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "l'opció «%s» només està permesa en mode de llista" +#: builtin/tag.c #, c-format msgid "'%s' is not a valid tag name." msgstr "«%s» no és un nom d'etiqueta và lid." +#: builtin/tag.c #, c-format msgid "tag '%s' already exists" msgstr "l'etiqueta «%s» ja existeix" +#: builtin/tag.c sequencer.c #, c-format msgid "Invalid cleanup mode %s" msgstr "Mode de neteja no và lid %s" +#: builtin/tag.c #, c-format msgid "Updated tag '%s' (was %s)\n" msgstr "Etiqueta «%s» actualitzada (era %s)\n" +#: builtin/unpack-objects.c msgid "pack exceeds maximum allowed size" msgstr "el paquet supera la mida mà xima permesa" +#: builtin/unpack-objects.c msgid "failed to write object in stream" msgstr "no s'ha pogut escriure l'objecte al flux" +#: builtin/unpack-objects.c #, c-format msgid "inflate returned (%d)" msgstr "inflate ha retornat (%d)" +#: builtin/unpack-objects.c msgid "invalid blob object from stream" msgstr "l'objecte blob del flux no és và lid" +#: builtin/unpack-objects.c msgid "Unpacking objects" msgstr "S'estan desempaquetant els objectes" +#: builtin/update-index.c #, c-format msgid "failed to create directory %s" msgstr "s'ha produït un error en crear el directori %s" +#: builtin/update-index.c #, c-format msgid "failed to delete file %s" msgstr "s'ha produït un error en suprimir el fitxer %s" +#: builtin/update-index.c #, c-format msgid "failed to delete directory %s" msgstr "s'ha produït un error en suprimir el directori %s" +#: builtin/update-index.c #, c-format msgid "Testing mtime in '%s' " msgstr "S'està provant mtime en «%s» " +#: builtin/update-index.c msgid "directory stat info does not change after adding a new file" msgstr "" "la informació de stat de directori no canvia després d'afegir un fitxer nou" +#: builtin/update-index.c msgid "directory stat info does not change after adding a new directory" msgstr "" "la informació de stat de directori no canvia després d'afegir un directori " "nou" +#: builtin/update-index.c msgid "directory stat info changes after updating a file" msgstr "" "la informació de stat de directori canvia després d'actualitzar un fitxer" +#: builtin/update-index.c msgid "directory stat info changes after adding a file inside subdirectory" msgstr "" "la informació de stat de directori canvia després d'afegir un fitxer dins " "d'un subdirectori" +#: builtin/update-index.c msgid "directory stat info does not change after deleting a file" msgstr "" "la informació de stat de directori no canvia després de suprimir un fitxer" +#: builtin/update-index.c msgid "directory stat info does not change after deleting a directory" msgstr "" "la informació de stat de directori no canvia després de suprimir un directori" +#: builtin/update-index.c msgid " OK" msgstr " D'acord" +#: builtin/update-index.c msgid "git update-index [<options>] [--] [<file>...]" msgstr "git update-index [<opcions>] [--] [<fitxer>...]" +#: builtin/update-index.c msgid "continue refresh even when index needs update" msgstr "" "continua l'actualització encara que l'Ãndex necessiti una actualització" +#: builtin/update-index.c msgid "refresh: ignore submodules" msgstr "actualitza: ignora els submòduls" +#: builtin/update-index.c msgid "do not ignore new files" msgstr "no ignoris els fitxers nous" +#: builtin/update-index.c msgid "let files replace directories and vice-versa" msgstr "deixa que els fitxers reemplacin els directoris i viceversa" +#: builtin/update-index.c msgid "notice files missing from worktree" msgstr "tingues en compte els fitxers absents de l'arbre de treball" +#: builtin/update-index.c msgid "refresh even if index contains unmerged entries" msgstr "actualitza encara que l'Ãndex contingui entrades no fusionades" +#: builtin/update-index.c msgid "refresh stat information" msgstr "actualitza la informació d'estadÃstiques" +#: builtin/update-index.c msgid "like --refresh, but ignore assume-unchanged setting" msgstr "com --refresh, però ignora el parà metre assume-unchanged" +#: builtin/update-index.c msgid "<mode>,<object>,<path>" msgstr "<mode>,<objecte>,<camÃ>" +#: builtin/update-index.c msgid "add the specified entry to the index" msgstr "afegeix l'entrada especificada a l'Ãndex" +#: builtin/update-index.c msgid "mark files as \"not changing\"" msgstr "marca els fitxers com a «no canviant»" +#: builtin/update-index.c msgid "clear assumed-unchanged bit" msgstr "esborra el bit assumed-unchanged" +#: builtin/update-index.c msgid "mark files as \"index-only\"" msgstr "marca els fitxers com a «només Ãndex»" +#: builtin/update-index.c msgid "clear skip-worktree bit" msgstr "esborra el bit skip-worktree" +#: builtin/update-index.c msgid "do not touch index-only entries" msgstr "no toquis les entrades de només Ãndex" +#: builtin/update-index.c msgid "add to index only; do not add content to object database" msgstr "" "només afegeix a l'Ãndex; no afegeixis el contingut a la base de dades " "d'objectes" +#: builtin/update-index.c msgid "remove named paths even if present in worktree" msgstr "" "elimina els camins anomenats encara que estiguin presents en l'arbre de " "treball" +#: builtin/update-index.c msgid "with --stdin: input lines are terminated by null bytes" msgstr "amb --stdin: les lÃnies d'entrada acaben amb octets nuls" +#: builtin/update-index.c msgid "read list of paths to be updated from standard input" msgstr "llegeix la llista de camins a actualitzar des de l'entrada està ndard" +#: builtin/update-index.c msgid "add entries from standard input to the index" msgstr "afegeix les entrades de l'entrada està ndard a l'Ãndex" +#: builtin/update-index.c msgid "repopulate stages #2 and #3 for the listed paths" msgstr "reemplena les «stage» #2 i #3 per als camins llistats" +#: builtin/update-index.c msgid "only update entries that differ from HEAD" msgstr "només actualitza les entrades que difereixin de HEAD" +#: builtin/update-index.c msgid "ignore files missing from worktree" msgstr "ignora els fitxers absents de l'arbre de treball" +#: builtin/update-index.c msgid "report actions to standard output" msgstr "informa de les accions en la sortida està ndard" +#: builtin/update-index.c msgid "(for porcelains) forget saved unresolved conflicts" msgstr "(per a porcellanes) oblida't dels conflictes no resolts ni desats" +#: builtin/update-index.c msgid "write index in this format" msgstr "escriu l'Ãndex en aquest format" +#: builtin/update-index.c msgid "report on-disk index format version" msgstr "informa sobre la versió del format de l'Ãndex del disc" +#: builtin/update-index.c msgid "enable or disable split index" msgstr "habilita o inhabilita l'Ãndex dividit" +#: builtin/update-index.c msgid "enable/disable untracked cache" msgstr "habilita/inhabilita la memòria cau no seguida" +#: builtin/update-index.c msgid "test if the filesystem supports untracked cache" msgstr "prova si el sistema de fitxers admet la memòria cau no seguida" +#: builtin/update-index.c msgid "enable untracked cache without testing the filesystem" msgstr "habilita la memòria cau no seguida sense provar el sistema de fitxers" +#: builtin/update-index.c msgid "write out the index even if is not flagged as changed" msgstr "escriu l'Ãndex encara que no estigui marcat com a canviat" +#: builtin/update-index.c msgid "enable or disable file system monitor" msgstr "habilita o inhabilita el monitor del sistema de fitxers" +#: builtin/update-index.c msgid "mark files as fsmonitor valid" msgstr "marca els fitxers com a và lids pel fsmonitor" +#: builtin/update-index.c msgid "clear fsmonitor valid bit" msgstr "esborra el bit de validesa del fsmonitor" +#: builtin/update-index.c #, c-format msgid "%d\n" msgstr "%d\n" +#: builtin/update-index.c #, c-format msgid "index-version: was %d, set to %d" msgstr "index-version: era %d, s'ha establert a %d" +#: builtin/update-index.c msgid "" "core.splitIndex is set to false; remove or change it, if you really want to " "enable split index" @@ -13462,6 +17156,7 @@ msgstr "" "core.splitIndex està establert a fals; elimineu-lo o canviar-lo, si realment " "voleu habilitar l'Ãndex dividit" +#: builtin/update-index.c msgid "" "core.splitIndex is set to true; remove or change it, if you really want to " "disable split index" @@ -13469,6 +17164,7 @@ msgstr "" "core.splitIndex està establert a cert; elimineu-lo o canvieu-lo, si realment " "voleu inhabilitar l'Ãndex dividit" +#: builtin/update-index.c msgid "" "core.untrackedCache is set to true; remove or change it, if you really want " "to disable the untracked cache" @@ -13476,9 +17172,11 @@ msgstr "" "core.untrackedCache està establert a cert; elimineu-lo o canvieu-lo, si " "realment voleu inhabilitar el cau no seguit" +#: builtin/update-index.c msgid "Untracked cache disabled" msgstr "La memòria cau no seguida està inhabilitada" +#: builtin/update-index.c msgid "" "core.untrackedCache is set to false; remove or change it, if you really want " "to enable the untracked cache" @@ -13486,96 +17184,124 @@ msgstr "" "core.untrackedCache està establert a fals; elimineu-lo o canviar-lo, si " "realment voleu habilitar el cau no seguit" +#: builtin/update-index.c #, c-format msgid "Untracked cache enabled for '%s'" msgstr "La memòria cau no seguida està habilitada per a «%s»" +#: builtin/update-index.c msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor" msgstr "" "core.fsmonitor està establert a fals; establiu-lo a cert si realment voleu " "habilitar fsmonitor" +#: builtin/update-index.c msgid "fsmonitor enabled" msgstr "fsmonitor habilitat" +#: builtin/update-index.c msgid "" "core.fsmonitor is set; remove it if you really want to disable fsmonitor" msgstr "" "core.fsmonitor està establert a cert; elimineu-lo si realment voleu " "inhabilitar fsmonitor" +#: builtin/update-index.c msgid "fsmonitor disabled" msgstr "fsmonitor inhabilitat" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<opcions>] -d <nom-de-referència> [<valor-antic>]" +#: builtin/update-ref.c +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<opcions>] -d <nom-referència> [<oid-vell>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "" -"git update-ref [<opcions>] <nom-de-referència> <valor-nou> [<valor-antic>]" +#: builtin/update-ref.c +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<opcions>] <nom-referència> <oid-nou> [<oid-vell>]" +#: builtin/update-ref.c msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<opcions>] --stdin [-z]" +#: builtin/update-ref.c msgid "delete the reference" msgstr "suprimeix la referència" +#: builtin/update-ref.c msgid "update <refname> not the one it points to" -msgstr "actualitza <nom de referència>, no la que apunti" +msgstr "actualitza <nom-referència>, no la que apunti" +#: builtin/update-ref.c msgid "stdin has NUL-terminated arguments" msgstr "stdin té arguments acabats amb NUL" +#: builtin/update-ref.c msgid "read updates from stdin" msgstr "llegeix les actualitzacions des de stdin" +#: builtin/update-server-info.c msgid "update the info files from scratch" msgstr "actualitza els fitxers d'informació des de zero" +#: builtin/upload-pack.c msgid "" "git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n" " [--advertise-refs] <directory>" msgstr "" "git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n" -" [--advertise-refs] <directory>" +" [--advertise-refs] <directori>" +#: builtin/upload-pack.c t/helper/test-serve-v2.c msgid "quit after a single request/response exchange" msgstr "surt després d'un sol intercanvi de sol·licitud/resposta" +#: builtin/upload-pack.c msgid "serve up the info/refs for git-http-backend" msgstr "serveix les info/refs per a git-http-backend" +#: builtin/upload-pack.c msgid "do not try <directory>/.git/ if <directory> is no Git directory" msgstr "" "no intentis <directori>/.git/ si <directori> no és cap directori del Git" +#: builtin/upload-pack.c msgid "interrupt transfer after <n> seconds of inactivity" msgstr "interromp la transferència després de <n> segons d'inactivitat" +#: builtin/verify-commit.c msgid "git verify-commit [-v | --verbose] [--raw] <commit>..." msgstr "git verify-commit [-v | --verbose] [--raw] <comissió>..." +#: builtin/verify-commit.c msgid "print commit contents" msgstr "imprimeix els continguts de la comissió" +#: builtin/verify-commit.c builtin/verify-tag.c msgid "print raw gpg status output" msgstr "imprimeix la sortida crua de l'estat gpg" +#: builtin/verify-pack.c msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." -msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." +msgstr "" +"git verify-pack [-v | --verbose] [-s | --stat-only] [--] <paquet>.idx..." +#: builtin/verify-pack.c msgid "verbose" msgstr "detallat" +#: builtin/verify-pack.c msgid "show statistics only" msgstr "mostra només estadÃstiques" +#: builtin/verify-tag.c msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..." -msgstr "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..." +msgstr "" +"git verify-tag [-v | --verbose] [--format=<format>] [--raw] <etiqueta>..." +#: builtin/verify-tag.c msgid "print tag contents" msgstr "imprimeix els continguts de l'etiqueta" +#: builtin/worktree.c msgid "" "git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n" " [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]" @@ -13583,30 +17309,39 @@ msgstr "" "git worktree add [-f] [--detach] [--checkout] [--lock [--reason <cadena>]]\n" " [--orphan] [(-b | -B) <new-branch>] <camÃ> [<commit-ish>]" +#: builtin/worktree.c msgid "git worktree list [-v | --porcelain [-z]]" msgstr "git worktree list [-v | --porcelain [-z]]" +#: builtin/worktree.c msgid "git worktree lock [--reason <string>] <worktree>" -msgstr "git worktree lock [--reason <string>] <worktree>" +msgstr "git worktree lock [--reason <cadena>] <arbre-treball>" +#: builtin/worktree.c msgid "git worktree move <worktree> <new-path>" -msgstr "git worktree move <arbre de treball> <camÃ-nou>" +msgstr "git worktree move <arbre-treball> <camÃ-nou>" +#: builtin/worktree.c msgid "git worktree prune [-n] [-v] [--expire <expire>]" msgstr "git worktree prune [-n] [-v] [--expire <expire>]" +#: builtin/worktree.c msgid "git worktree remove [-f] <worktree>" -msgstr "git worktree remove [-f] <worktree>" +msgstr "git worktree remove [-f] <arbre-treball>" +#: builtin/worktree.c msgid "git worktree repair [<path>...]" msgstr "git worktree repair [<camÃ>...]" +#: builtin/worktree.c msgid "git worktree unlock <worktree>" -msgstr "git worktree unlock <worktree>" +msgstr "git worktree unlock <arbre-treball>" +#: builtin/worktree.c msgid "No possible source branch, inferring '--orphan'" msgstr "No hi ha cap branca d'origen possible, inferint «--orphan»" +#: builtin/worktree.c #, c-format msgid "" "If you meant to create a worktree containing a new unborn branch\n" @@ -13621,6 +17356,7 @@ msgstr "" "\n" " git worktree add --orphan -b %s %s\n" +#: builtin/worktree.c #, c-format msgid "" "If you meant to create a worktree containing a new unborn branch\n" @@ -13635,24 +17371,30 @@ msgstr "" "\n" " git worktree add --orphan %s\n" +#: builtin/worktree.c #, c-format msgid "Removing %s/%s: %s" msgstr "S'està eliminant %s/%s: %s" +#: builtin/worktree.c msgid "report pruned working trees" msgstr "informa dels arbres de treball podats" +#: builtin/worktree.c msgid "expire working trees older than <time>" msgstr "fes caducar els arbres de treball més antics que <data>" +#: builtin/worktree.c #, c-format msgid "'%s' already exists" msgstr "«%s» ja existeix" +#: builtin/worktree.c #, c-format msgid "unusable worktree destination '%s'" msgstr "destinació de l'arbre de treball no utilitzable «%s»" +#: builtin/worktree.c #, c-format msgid "" "'%s' is a missing but locked worktree;\n" @@ -13662,6 +17404,7 @@ msgstr "" "useu «%s -f -f» per a sobreescriure-ho, o «unlock» i «prune» o «remove» per " "a netejar" +#: builtin/worktree.c #, c-format msgid "" "'%s' is a missing but already registered worktree;\n" @@ -13670,54 +17413,66 @@ msgstr "" "manca «%s» però ja està registrat a l'arbre de treball;\n" "useu «%s» per a sobreescriure-ho, o «prune» o «remove» per a netejar" +#: builtin/worktree.c #, c-format msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly" msgstr "" "no s'ha pogut copiar «%s» a «%s»; «sparse-checkout» pot no funcionar " "correctament" +#: builtin/worktree.c #, c-format msgid "failed to copy worktree config from '%s' to '%s'" msgstr "" "no s'ha pogut copiar la configuració de l'arbre de treball de «%s» a «%s»" +#: builtin/worktree.c #, c-format msgid "failed to unset '%s' in '%s'" msgstr "no s'ha pogut desassignar «%s» a «%s»" +#: builtin/worktree.c #, c-format msgid "could not create directory of '%s'" msgstr "no s'ha pogut crear directori de «%s»" +#: builtin/worktree.c msgid "initializing" msgstr "s'està inicialitzant" +#: builtin/worktree.c #, c-format msgid "could not find created worktree '%s'" msgstr "no s'ha pogut trobar l'arbre de treball creat «%s»" +#: builtin/worktree.c #, c-format msgid "Preparing worktree (new branch '%s')" msgstr "S'està preparant l'arbre de treball (branca nova «%s»)" +#: builtin/worktree.c #, c-format msgid "Preparing worktree (resetting branch '%s'; was at %s)" msgstr "" "S'està preparant l'arbre de treball (s'està reiniciant la branca «%s»; " "estava a %s)" +#: builtin/worktree.c #, c-format msgid "Preparing worktree (checking out '%s')" msgstr "S'està preparant l'arbre de treball (s'està agafant «%s»)" +#: builtin/worktree.c #, c-format msgid "unreachable: invalid reference: %s" msgstr "no accessible: referència no và lida: %s" +#: builtin/worktree.c #, c-format msgid "Preparing worktree (detached HEAD %s)" msgstr "S'està preparant l'arbre de treball (HEAD %s separat)" +#: builtin/worktree.c #, c-format msgid "" "HEAD points to an invalid (or orphaned) reference.\n" @@ -13728,6 +17483,7 @@ msgstr "" "Camà HEAD: «%s»\n" "Contingut HEAD: «%s»" +#: builtin/worktree.c msgid "" "No local or remote refs exist despite at least one remote\n" "present, stopping; use 'add -f' to override or fetch a remote first" @@ -13735,94 +17491,120 @@ msgstr "" "No hi ha referències locals o remotes malgrat hi existeix almenys un\n" "remot, aturada; useu «add -f» per a anul·lar o obtenir primer un remot" +#: builtin/worktree.c msgid "checkout <branch> even if already checked out in other worktree" msgstr "agafa <branca> encara que sigui agafada en altre arbre de treball" +#: builtin/worktree.c msgid "create a new branch" msgstr "crea una branca nova" +#: builtin/worktree.c msgid "create or reset a branch" msgstr "crea o restableix una branca" +#: builtin/worktree.c msgid "create unborn branch" msgstr "crea una branca no nascuda" +#: builtin/worktree.c msgid "populate the new working tree" msgstr "emplena l'arbre de treball nou" +#: builtin/worktree.c msgid "keep the new working tree locked" msgstr "mantén l'arbre de treball nou bloquejat" +#: builtin/worktree.c msgid "reason for locking" msgstr "raó per a bloquejar" +#: builtin/worktree.c msgid "set up tracking mode (see git-branch(1))" msgstr "configura el mode de seguiment (vegeu git-branch(1))" +#: builtin/worktree.c msgid "try to match the new branch name with a remote-tracking branch" msgstr "" "prova de fer coincidir el nom de la branca nova amb una branca amb seguiment " "remot" +#: builtin/worktree.c diff.c parse-options.c #, c-format msgid "options '%s', '%s', and '%s' cannot be used together" msgstr "les opcions «%s», «%s», i «%s» no es poden usar juntes" +#: builtin/worktree.c #, c-format msgid "option '%s' and commit-ish cannot be used together" msgstr "opció «%s» i les de comissió no es poden usar juntes" +#: builtin/worktree.c msgid "added with --lock" msgstr "afegit amb --lock" +#: builtin/worktree.c msgid "--[no-]track can only be used if a new branch is created" msgstr "--[no-]track només es pot usar si es crea una branca nova" +#: builtin/worktree.c msgid "show extended annotations and reasons, if available" msgstr "mostra les anotacions esteses i les raons, si estan disponibles" +#: builtin/worktree.c msgid "add 'prunable' annotation to worktrees older than <time>" msgstr "" "afegeix l'anotació «prunable» als arbres de treball més antics que <data>" +#: builtin/worktree.c msgid "terminate records with a NUL character" msgstr "finalitza els registres amb un carà cter NUL" +#: builtin/worktree.c #, c-format msgid "'%s' is not a working tree" msgstr "«%s» no és un arbre de treball" +#: builtin/worktree.c msgid "The main working tree cannot be locked or unlocked" msgstr "No es pot bloquejar ni desbloquejar l'arbre de treball principal" +#: builtin/worktree.c #, c-format msgid "'%s' is already locked, reason: %s" msgstr "«%s» ja està bloquejat, raó: «%s»" +#: builtin/worktree.c #, c-format msgid "'%s' is already locked" msgstr "«%s» ja està bloquejat" +#: builtin/worktree.c #, c-format msgid "'%s' is not locked" msgstr "«%s» no està bloquejat" +#: builtin/worktree.c msgid "working trees containing submodules cannot be moved or removed" msgstr "" "els arbres de treball que contenen submòduls no es poden moure ni eliminar" +#: builtin/worktree.c msgid "force move even if worktree is dirty or locked" msgstr "" "força el moviment encara que l'arbre de treball estigui brut o bloquejat" +#: builtin/worktree.c #, c-format msgid "'%s' is a main working tree" msgstr "«%s» és un arbre de treball principal" +#: builtin/worktree.c #, c-format msgid "could not figure out destination name from '%s'" msgstr "no s'ha pogut deduir el nom de destà des de «%s»" +#: builtin/worktree.c #, c-format msgid "" "cannot move a locked working tree, lock reason: %s\n" @@ -13831,6 +17613,7 @@ msgstr "" "no es pot moure un arbre de treball bloquejat, raó del bloqueig: %s\n" "useu primer «move -f -f» per a sobreescriure'l o desbloquejar-lo primer" +#: builtin/worktree.c msgid "" "cannot move a locked working tree;\n" "use 'move -f -f' to override or unlock first" @@ -13838,31 +17621,38 @@ msgstr "" "no es pot moure un arbre de treball bloquejat;\n" "useu primer «move -f -f» per a sobreescriure'l o desbloquejar-lo primer" +#: builtin/worktree.c #, c-format msgid "validation failed, cannot move working tree: %s" msgstr "la validació ha fallat, no es pot moure l'arbre de treball: %s" +#: builtin/worktree.c #, c-format msgid "failed to move '%s' to '%s'" msgstr "s'ha produït un error en moure «%s» a «%s»" +#: builtin/worktree.c #, c-format msgid "failed to run 'git status' on '%s'" msgstr "no s'ha pogut executar «git status» a «%s»" +#: builtin/worktree.c #, c-format msgid "'%s' contains modified or untracked files, use --force to delete it" msgstr "" "«%s» conté fitxers modificats o no seguits, useu --force per a suprimir-los" +#: builtin/worktree.c #, c-format msgid "failed to run 'git status' on '%s', code %d" msgstr "no s'ha pogut executar «git status» a «%s», codi %d" +#: builtin/worktree.c msgid "force removal even if worktree is dirty or locked" msgstr "" "força l'eliminació encara que l'arbre de treball estigui brut o bloquejat" +#: builtin/worktree.c #, c-format msgid "" "cannot remove a locked working tree, lock reason: %s\n" @@ -13871,6 +17661,7 @@ msgstr "" "no es pot suprimir un arbre de treball bloquejat, raó del bloqueig: %s\n" "useu primer «remove -f -f» per a sobreescriure'l o desbloquejar-lo" +#: builtin/worktree.c msgid "" "cannot remove a locked working tree;\n" "use 'remove -f -f' to override or unlock first" @@ -13878,109 +17669,135 @@ msgstr "" "no es pot suprimir un arbre de treball bloquejat;\n" "useu primer «remove -f -f» per a sobreescriure'l o desbloquejar-lo" +#: builtin/worktree.c #, c-format msgid "validation failed, cannot remove working tree: %s" msgstr "la validació ha fallat, no es pot suprimir l'arbre de treball: %s" +#: builtin/worktree.c #, c-format msgid "repair: %s: %s" msgstr "repara: %s: %s" +#: builtin/worktree.c #, c-format msgid "error: %s: %s" msgstr "error: %s: %s" +#: builtin/write-tree.c msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]" msgstr "git write-tree [--missing-ok] [--prefix=<prefix>/]" +#: builtin/write-tree.c msgid "<prefix>/" msgstr "<prefix>/" +#: builtin/write-tree.c msgid "write tree object for a subdirectory <prefix>" msgstr "escriu l'objecte d'arbre per a un subdirectori <prefix>" +#: builtin/write-tree.c msgid "only useful for debugging" msgstr "només útil per a la depuració" +#: bulk-checkin.c msgid "core.fsyncMethod = batch is unsupported on this platform" msgstr "core.fsyncMethod = batch no és compatible amb aquesta plataforma" +#: bundle-uri.c #, c-format msgid "could not parse bundle list key %s with value '%s'" msgstr "" "no s'ha pogut analitzar la clau de llista de paquets %s amb el valor «%s»" +#: bundle-uri.c #, c-format msgid "bundle list at '%s' has no mode" msgstr "la llista de farcells a «%s» no té mode" +#: bundle-uri.c msgid "failed to create temporary file" msgstr "no s'ha pogut crear un fitxer temporal" +#: bundle-uri.c msgid "insufficient capabilities" msgstr "capacitats insuficients" +#: bundle-uri.c #, c-format msgid "file downloaded from '%s' is not a bundle" msgstr "el fitxer baixat de «%s» no és un paquet" +#: bundle-uri.c msgid "failed to store maximum creation token" msgstr "no s'ha pogut emmagatzemar el testimoni de creació mà xim" +#: bundle-uri.c #, c-format msgid "unrecognized bundle mode from URI '%s'" msgstr "no s'ha reconegut el model del farcell de l'URI «%s»" +#: bundle-uri.c #, c-format msgid "exceeded bundle URI recursion limit (%d)" msgstr "s'ha excedit el lÃmit de recursió URI del paquet (%d)" +#: bundle-uri.c #, c-format msgid "failed to download bundle from URI '%s'" msgstr "no s'ha pogut baixar el paquet de l'URI «%s»" +#: bundle-uri.c #, c-format msgid "file at URI '%s' is not a bundle or bundle list" msgstr "el fitxer a l'URI «%s» no és farcell o una llista de farcells" +#: bundle-uri.c #, c-format msgid "bundle-uri: unexpected argument: '%s'" msgstr "bundle-uri: argument inesperat: «%s»" +#: bundle-uri.c msgid "bundle-uri: expected flush after arguments" msgstr "bundle-uri: s'esperava una neteja després dels arguments" +#: bundle-uri.c msgid "bundle-uri: got an empty line" msgstr "bundle-uri: té una lÃnia buida" +#: bundle-uri.c msgid "bundle-uri: line is not of the form 'key=value'" msgstr "bundle-uri: la lÃnia no és de la forma «key=value»" +#: bundle-uri.c msgid "bundle-uri: line has empty key or value" msgstr "bundle-uri: la lÃnia té una clau o un valor buit" +#: bundle.c #, c-format msgid "unrecognized bundle hash algorithm: %s" msgstr "algoritme de resum del farcell desconegut: %s" +#: bundle.c #, c-format msgid "unknown capability '%s'" msgstr "funcionalitat «%s» desconeguda" +#: bundle.c #, c-format msgid "'%s' does not look like a v2 or v3 bundle file" msgstr "«%s» no sembla un fitxer de farcell v2 o v3" +#: bundle.c #, c-format msgid "unrecognized header: %s%s (%d)" msgstr "capçalera no reconeguda: %s%s (%d)" +#: bundle.c msgid "Repository lacks these prerequisite commits:" msgstr "Al repositori li manquen aquestes comissions prerequerides:" -msgid "need a repository to verify a bundle" -msgstr "cal un repositori per a verificar un farcell" - +#: bundle.c msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -13988,685 +17805,904 @@ msgstr "" "hi ha algunes comissions requerides al magatzem d'objectes, però no estan " "connectades a l'historial del repositori" +#: bundle.c #, c-format msgid "The bundle contains this ref:" msgid_plural "The bundle contains these %<PRIuMAX> refs:" msgstr[0] "El farcell conté aquesta referència:" msgstr[1] "El farcell conté aquestes %<PRIuMAX> referències:" +#: bundle.c msgid "The bundle records a complete history." msgstr "El farcell registra una història completa." +#: bundle.c #, c-format msgid "The bundle requires this ref:" msgid_plural "The bundle requires these %<PRIuMAX> refs:" msgstr[0] "El farcell requereix aquesta referència:" msgstr[1] "El farcell requereix aquestes %<PRIuMAX> referències:" +#: bundle.c #, c-format msgid "The bundle uses this hash algorithm: %s" msgstr "El farcell utilitza aquest algoritme de resum: %s" +#: bundle.c #, c-format msgid "The bundle uses this filter: %s" msgstr "El farcell utilitza aquest filtre: %s" +#: bundle.c msgid "unable to dup bundle descriptor" msgstr "no s'ha pogut duplicar el descriptor del farcell" +#: bundle.c msgid "Could not spawn pack-objects" msgstr "No s'ha pogut engendrar el pack-objects" +#: bundle.c msgid "pack-objects died" msgstr "el pack-objects s'ha mort" +#: bundle.c #, c-format msgid "ref '%s' is excluded by the rev-list options" msgstr "les opcions de la llista de revisions exclouen la referència «%s»" +#: bundle.c #, c-format msgid "unsupported bundle version %d" msgstr "versió del farcell no compatible %d" +#: bundle.c #, c-format msgid "cannot write bundle version %d with algorithm %s" msgstr "no es pot escriure la versió del farcell %d amb l'algorisme %s" +#: bundle.c msgid "Refusing to create empty bundle." msgstr "S'està refusant crear un farcell buit." +#: bundle.c #, c-format msgid "cannot create '%s'" msgstr "no es pot crear «%s»" +#: bundle.c msgid "index-pack died" msgstr "l'index-pack s'ha mort" +#: chunk-format.c msgid "terminating chunk id appears earlier than expected" msgstr "" "l'identificador de fragment de finalització apareix abans del que s'esperava" +#: chunk-format.c #, c-format msgid "chunk id %<PRIx32> not %d-byte aligned" -msgstr "ID del fragment %<PRIx32> no alineat %d-byte" +msgstr "ID del fragment %<PRIx32> no alineat a %d-octets" +#: chunk-format.c #, c-format msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>" msgstr "desplaçament incorrecte del fragment %<PRIx64> i %<PRIx64>" +#: chunk-format.c #, c-format msgid "duplicate chunk ID %<PRIx32> found" msgstr "s'ha trobat un ID del fragment %<PRIx32> duplicat" +#: chunk-format.c #, c-format msgid "final chunk has non-zero id %<PRIx32>" msgstr "el fragment final té un id %<PRIx32> que no és zero" +#: chunk-format.c msgid "invalid hash version" msgstr "especificació de resum no và lida" +#: color.c #, c-format msgid "invalid color value: %.*s" msgstr "valor de color no và lid: %.*s" +#: command-list.h msgid "Add file contents to the index" msgstr "Afegeix els continguts dels fitxers a l'Ãndex" +#: command-list.h msgid "Apply a series of patches from a mailbox" msgstr "Aplica una sèrie de pedaços des d'una bústia de correu" +#: command-list.h msgid "Annotate file lines with commit information" msgstr "Anota les lÃnies del fitxer amb la informació de la comissió" +#: command-list.h msgid "Apply a patch to files and/or to the index" msgstr "Aplica un pedaç a fitxer i/o a l'Ãndex" +#: command-list.h msgid "Import a GNU Arch repository into Git" msgstr "Importa un repositori GNU Arch a Git" +#: command-list.h msgid "Create an archive of files from a named tree" msgstr "Crea un arxiu de fitxers des d'un arbre amb nom" +#: command-list.h msgid "Use binary search to find the commit that introduced a bug" msgstr "Troba per cerca binà ria el canvi que hagi introduït un defecte" +#: command-list.h msgid "Show what revision and author last modified each line of a file" msgstr "" "Mostra quina revisió i autor ha modificat per últim cop cada lÃnia d'un " "fitxer" +#: command-list.h msgid "List, create, or delete branches" msgstr "Llista, crea o suprimeix branques" +#: command-list.h msgid "Collect information for user to file a bug report" msgstr "Recopila la informació per a l'usuari per a enviar un informe d'error" +#: command-list.h msgid "Move objects and refs by archive" msgstr "Mou els objectes i les referències per arxiu" +#: command-list.h msgid "Provide contents or details of repository objects" msgstr "Proporcioneu el contingut o els detalls dels objectes del repositori" +#: command-list.h msgid "Display gitattributes information" msgstr "Mostra la informació de .gitattributes" +#: command-list.h msgid "Debug gitignore / exclude files" msgstr "Depura gitignore / fitxers d'exclusió" +#: command-list.h msgid "Show canonical names and email addresses of contacts" msgstr "Mostra els noms canònics i les adreces electròniques dels contactes" +#: command-list.h msgid "Ensures that a reference name is well formed" msgstr "Assegura que un nom de referència està ben format" +#: command-list.h msgid "Switch branches or restore working tree files" msgstr "Canvia de branca o restaura els fitxers de l'arbre de treball" +#: command-list.h msgid "Copy files from the index to the working tree" msgstr "Copia fitxers des de l'Ãndex a l'arbre de treball" +#: command-list.h msgid "Find commits yet to be applied to upstream" msgstr "Troba les comissions que encara s'han d'aplicar a la font" +#: command-list.h msgid "Apply the changes introduced by some existing commits" msgstr "Aplica els canvis introduïts per algunes comissions existents" +#: command-list.h msgid "Graphical alternative to git-commit" msgstr "Alternativa grà fica a git-commit" +#: command-list.h msgid "Remove untracked files from the working tree" msgstr "Elimina els fitxers no seguits de l'arbre de treball" +#: command-list.h msgid "Clone a repository into a new directory" msgstr "Clona un repositori a un directori nou" +#: command-list.h msgid "Display data in columns" msgstr "Mostra les dades en columnes" +#: command-list.h msgid "Record changes to the repository" msgstr "Registra els canvis al repositori" +#: command-list.h msgid "Write and verify Git commit-graph files" msgstr "Escriu i verifica els fitxers commit-graph de Git" +#: command-list.h msgid "Create a new commit object" msgstr "Crea un objecte de comissió nou" +#: command-list.h msgid "Get and set repository or global options" msgstr "Obté o estableix opcions de repositori o globals" +#: command-list.h msgid "Count unpacked number of objects and their disk consumption" msgstr "Compta el nombre d'objectes desempaquetats i el seu consum de disc" +#: command-list.h msgid "Retrieve and store user credentials" msgstr "Recupera i desa les credencials d'usuari" +#: command-list.h msgid "Helper to temporarily store passwords in memory" msgstr "Ajudant per a emmagatzemar temporalment les contrasenyes en memòria" +#: command-list.h msgid "Helper to store credentials on disk" msgstr "Ajudant per a emmagatzemar credencials a disc" +#: command-list.h msgid "Export a single commit to a CVS checkout" msgstr "Exporta en una sola comissió a CVS checkout" +#: command-list.h msgid "Salvage your data out of another SCM people love to hate" msgstr "Salveu les vostres dades d'un altre SMC al que la gent li agrada odiar" +#: command-list.h msgid "A CVS server emulator for Git" msgstr "Un emulador de servidor CVS per al Git" +#: command-list.h msgid "A really simple server for Git repositories" msgstr "Un servidor realment senzill per a repositoris Git" +#: command-list.h msgid "Give an object a human readable name based on an available ref" msgstr "" "Dona un nom llegible per a humans basant-se en les referències disponibles" +#: command-list.h msgid "Generate a zip archive of diagnostic information" msgstr "Genera un arxiu zip d'informació de diagnòstic" +#: command-list.h msgid "Show changes between commits, commit and working tree, etc" msgstr "" "Mostra els canvis entre comissions, la comissió i l'arbre de treball, etc" +#: command-list.h msgid "Compares files in the working tree and the index" msgstr "Compara fitxers en l'arbre de treball i l'Ãndex" +#: command-list.h msgid "Compare a tree to the working tree or index" msgstr "Compara un arbre amb l'arbre de treball o l'Ãndex" +#: command-list.h msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "Compara el contingut i el mode dels blobs trobats a través de dos objectes " "d'arbre" +#: command-list.h msgid "Show changes using common diff tools" msgstr "Mostra els canvis usant eines diff comunes" +#: command-list.h msgid "Git data exporter" msgstr "Exportador de dades del Git" +#: command-list.h msgid "Backend for fast Git data importers" msgstr "Rerefons per a importadors rà pids de dades de Git" +#: command-list.h msgid "Download objects and refs from another repository" msgstr "Baixa objectes i referències d'un altre repositori" +#: command-list.h msgid "Receive missing objects from another repository" msgstr "Rep els objectes que manquen des d'un altre repositori" +#: command-list.h msgid "Rewrite branches" msgstr "Torna a escriure les branques" +#: command-list.h msgid "Produce a merge commit message" msgstr "Produeix un missatge de comissió de fusió" +#: command-list.h msgid "Output information on each ref" msgstr "Mostra la informació en cada referència" +#: command-list.h msgid "Run a Git command on a list of repositories" msgstr "Executa una ordre Git en una llista de repositoris" +#: command-list.h msgid "Prepare patches for e-mail submission" msgstr "Prepara pedaços per a enviar-los per correu electrònic" +#: command-list.h msgid "Verifies the connectivity and validity of the objects in the database" msgstr "Verifica la connectivitat i validesa dels objectes a la base de dades" +#: command-list.h msgid "Cleanup unnecessary files and optimize the local repository" msgstr "Neteja els fitxers innecessaris i optimitza el repositori local" +#: command-list.h msgid "Extract commit ID from an archive created using git-archive" msgstr "Extreu l'ID de la comissió d'un arxiu creat amb el git-archive" +#: command-list.h msgid "Print lines matching a pattern" msgstr "Imprimeix les lÃnies coincidents amb un patró" +#: command-list.h msgid "A portable graphical interface to Git" msgstr "Una interfÃcie grà fica portable per al Git" +#: command-list.h msgid "Compute object ID and optionally create an object from a file" msgstr "" "Calcula l'ID de l'objecte i opcionalment crea un objecte des del fitxer" +#: command-list.h msgid "Display help information about Git" msgstr "Mostra informació d'ajuda del Git" +#: command-list.h msgid "Run git hooks" msgstr "Executa els lligams del git" +#: command-list.h msgid "Server side implementation of Git over HTTP" msgstr "Implementació al servidor del Git sobre HTTP" +#: command-list.h msgid "Download from a remote Git repository via HTTP" msgstr "Baixa des d'un repositori Git remot via HTTP" +#: command-list.h msgid "Push objects over HTTP/DAV to another repository" msgstr "Pujar objectes sobre HTTP/DAV a un altre repositori" +#: command-list.h msgid "Send a collection of patches from stdin to an IMAP folder" msgstr "" "Envia una col·lecció de pedaços des de l'entrada està ndard a una carpeta IMAP" +#: command-list.h msgid "Build pack index file for an existing packed archive" msgstr "" "Construeix el fitxer d'Ãndex del paquet per a un arxiu empaquetat existent" +#: command-list.h msgid "Create an empty Git repository or reinitialize an existing one" msgstr "Crea un repositori de Git buit o reinicialitza un existent" +#: command-list.h msgid "Instantly browse your working repository in gitweb" msgstr "Navegueu instantà niament pel vostre repositori de treball a gitweb" +#: command-list.h msgid "Add or parse structured information in commit messages" msgstr "" "Afegeix o analitza la informació estructurada en els missatges de comissió" +#: command-list.h msgid "Show commit logs" msgstr "Mostra els registres de comissió" +#: command-list.h msgid "Show information about files in the index and the working tree" msgstr "Mostra informació sobre els fitxers a l'Ãndex i a l'arbre de treball" +#: command-list.h msgid "List references in a remote repository" msgstr "Mostra les referències d'un repositori remot" +#: command-list.h msgid "List the contents of a tree object" msgstr "Mostra els continguts d'un objecte de l'arbre" +#: command-list.h msgid "Extracts patch and authorship from a single e-mail message" msgstr "Extreu el pedaç i l'autoria d'un sol missatge de correu electrònic" +#: command-list.h msgid "Simple UNIX mbox splitter program" msgstr "Programa de divisió mbox simple per a UNIX" +#: command-list.h msgid "Run tasks to optimize Git repository data" msgstr "Executa tasques per a optimitzar les dades del repositori Git" +#: command-list.h msgid "Join two or more development histories together" msgstr "Uneix dues o més històries de desenvolupament" +#: command-list.h msgid "Find as good common ancestors as possible for a merge" msgstr "Troba els millors avantpassats comuns possibles per a una fusió" +#: command-list.h msgid "Run a three-way file merge" msgstr "Executa una fusió de fitxers de tres vies" +#: command-list.h msgid "Run a merge for files needing merging" msgstr "Executa una fusió per als fitxers que cal fusionar" +#: command-list.h msgid "The standard helper program to use with git-merge-index" msgstr "El programa d'ajuda està ndard a utilitzar amb git-merge-index" +#: command-list.h msgid "Perform merge without touching index or working tree" msgstr "Realitza la fusió sense tocar l'Ãndex o l'arbre de treball" +#: command-list.h msgid "Run merge conflict resolution tools to resolve merge conflicts" msgstr "" "Executa eines de resolució de conflictes per a resoldre conflictes de fusió" +#: command-list.h msgid "Creates a tag object with extra validation" msgstr "Crea un objecte etiqueta amb validació addicional" +#: command-list.h msgid "Build a tree-object from ls-tree formatted text" msgstr "Construeix un objecte en arbre a partir de text formatat amb ls-tree" +#: command-list.h msgid "Write and verify multi-pack-indexes" msgstr "Escriu i verifica els Ãndexs multipaquet" +#: command-list.h msgid "Move or rename a file, a directory, or a symlink" msgstr "Mou o canvia de nom a un fitxer, directori o enllaç simbòlic" +#: command-list.h msgid "Find symbolic names for given revs" msgstr "Cerca noms simbòlics per a les revisions donades" +#: command-list.h msgid "Add or inspect object notes" msgstr "Afegeix o inspecciona notes de l'objecte" +#: command-list.h msgid "Import from and submit to Perforce repositories" msgstr "Importa des de i envia a repositoris Perforce" +#: command-list.h msgid "Create a packed archive of objects" msgstr "Crea un arxiu empaquetat d'objectes" +#: command-list.h msgid "Find redundant pack files" msgstr "Troba fitxers empaquetats redundants" +#: command-list.h msgid "Pack heads and tags for efficient repository access" msgstr "" "Empaqueta els caps i les etiquetes per a un accés eficient al repositori" +#: command-list.h msgid "Compute unique ID for a patch" msgstr "Calcula un identificador únic per a cada pedaç" +#: command-list.h msgid "Prune all unreachable objects from the object database" msgstr "Poda tots els objectes no accessibles de la base de dades d'objectes" +#: command-list.h msgid "Remove extra objects that are already in pack files" msgstr "Elimina els objectes extres que ja estan en fitxers empaquetats" +#: command-list.h msgid "Fetch from and integrate with another repository or a local branch" msgstr "Obtén i integra amb un altre repositori o una branca local" +#: command-list.h msgid "Update remote refs along with associated objects" msgstr "" "Actualitza les referències remotes juntament amb els objectes associats" +#: command-list.h msgid "Applies a quilt patchset onto the current branch" msgstr "Aplica un conjunt de pedaços a la branca actual" +#: command-list.h msgid "Compare two commit ranges (e.g. two versions of a branch)" msgstr "Compara dos rangs de comissions (p. ex. dues versions d'una branca)" +#: command-list.h msgid "Reads tree information into the index" msgstr "Llegeix la informació de l'arbre a l'Ãndex" +#: command-list.h msgid "Reapply commits on top of another base tip" msgstr "Torna a aplicar les comissions sobre un altre punt de basament" +#: command-list.h msgid "Receive what is pushed into the repository" msgstr "Rep el que s'envia al repositori" +#: command-list.h msgid "Manage reflog information" msgstr "Gestiona la informació del registre de referències" +# Baix nivell / nivell baix +#: command-list.h +msgid "Low-level access to refs" +msgstr "Accés de baix nivell a referències" + +#: command-list.h msgid "Manage set of tracked repositories" msgstr "Gestiona el conjunt de repositoris seguits" +#: command-list.h msgid "Pack unpacked objects in a repository" msgstr "Empaqueta els objectes desempaquetats en un repositori" +#: command-list.h msgid "Create, list, delete refs to replace objects" msgstr "Crea, llista i esborra referències per a substituir objectes" +#: command-list.h msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too" msgstr "" "EXPERIMENTAL: torna a reproduir comissions sobre una nova base, també " "funciona amb repositoris nus" +#: command-list.h msgid "Generates a summary of pending changes" msgstr "Genera un resum dels canvis pendents" +#: command-list.h msgid "Reuse recorded resolution of conflicted merges" msgstr "Reutilitza la resolució registrada dels conflictes de fusió" +#: command-list.h msgid "Reset current HEAD to the specified state" msgstr "Restableix la HEAD actual a l'estat especificat" +#: command-list.h msgid "Restore working tree files" msgstr "Restaura els fitxers de l'arbre de treball" +#: command-list.h msgid "Lists commit objects in reverse chronological order" msgstr "Mostra les comissions en ordre topològic invers" +#: command-list.h msgid "Pick out and massage parameters" msgstr "Trieu i personalitzeu els parà metres" +#: command-list.h msgid "Revert some existing commits" msgstr "Reverteix comissions existents" +#: command-list.h msgid "Remove files from the working tree and from the index" msgstr "Elimina fitxers de l'arbre de treball i de l'Ãndex" +#: command-list.h msgid "Send a collection of patches as emails" msgstr "Envia una col·lecció de pedaços com a correus electrònics" +#: command-list.h msgid "Push objects over Git protocol to another repository" msgstr "Puja objectes sobre el protocol Git a un altre repositori" +#: command-list.h msgid "Git's i18n setup code for shell scripts" msgstr "" "Codi de configuració i18n del Git per als scripts de l'intèrpret d'ordres" +#: command-list.h msgid "Common Git shell script setup code" msgstr "Codi de scripts de configuració comuns pel Git shell" +#: command-list.h msgid "Restricted login shell for Git-only SSH access" msgstr "Intèrpret d'ordres d'entrada restringit només per a accés SSH al Git" +#: command-list.h msgid "Summarize 'git log' output" msgstr "Resumeix la sortida «git log»" +#: command-list.h msgid "Show various types of objects" msgstr "Mostra diversos tipus d'objectes" +#: command-list.h msgid "Show branches and their commits" msgstr "Mostra les branques i les seves comissions" +#: command-list.h msgid "Show packed archive index" msgstr "Mostra l'Ãndex d'arxius empaquetat" +#: command-list.h msgid "List references in a local repository" msgstr "Llista les referències en un repositori local" +#: command-list.h msgid "Reduce your working tree to a subset of tracked files" msgstr "Redueix l'arbre de treball a un subconjunt de fitxers seguits" +#: command-list.h msgid "Add file contents to the staging area" msgstr "Afegeix el contingut del fitxer a l'à rea de «staging»" +#: command-list.h msgid "Stash the changes in a dirty working directory away" msgstr "Fes «stash» dels canvis en un directori de treball brut" +#: command-list.h msgid "Show the working tree status" msgstr "Mostra l'estat de l'arbre de treball" +#: command-list.h msgid "Remove unnecessary whitespace" msgstr "Elimina l'espai en blanc innecessari" +#: command-list.h msgid "Initialize, update or inspect submodules" msgstr "Inicialitza, actualitza o inspecciona submòduls" +#: command-list.h msgid "Bidirectional operation between a Subversion repository and Git" msgstr "Operació bidireccional entre un repositori a Subversion i Git" +#: command-list.h msgid "Switch branches" msgstr "Commuta entre branques" +#: command-list.h msgid "Read, modify and delete symbolic refs" msgstr "Llegeix, modifica i suprimeix referències simbòliques" +#: command-list.h msgid "Create, list, delete or verify a tag object signed with GPG" msgstr "" "Crea, llista, suprimeix o verifica un objecte d'etiqueta signat amb GPG" +#: command-list.h msgid "Creates a temporary file with a blob's contents" msgstr "Crea un fitxer temporal amb els continguts dels blobs" +#: command-list.h msgid "Unpack objects from a packed archive" msgstr "Desempaqueta objectes d'un arxiu empaquetat" +#: command-list.h msgid "Register file contents in the working tree to the index" msgstr "Registra els continguts del fitxer en l'arbre de treball a l'Ãndex" +#: command-list.h msgid "Update the object name stored in a ref safely" msgstr "" "Actualitza el nom de l'objecte emmagatzemat en una referència de forma segura" +#: command-list.h msgid "Update auxiliary info file to help dumb servers" msgstr "" "Actualitza el fitxer d'informació auxiliar per a ajudar als servidors ximples" +#: command-list.h msgid "Send archive back to git-archive" msgstr "Envia l'arxiu de tornada al git-archive" +#: command-list.h msgid "Send objects packed back to git-fetch-pack" msgstr "Envia els objectes empaquetats de tornada al git-fetch-pack" +#: command-list.h msgid "Show a Git logical variable" msgstr "Mostra una variable lògica del Git" +#: command-list.h msgid "Check the GPG signature of commits" msgstr "Verifica la signatura GPG de les comissions" +#: command-list.h msgid "Validate packed Git archive files" msgstr "Valida els fitxers d'arxius Git empaquetats" +#: command-list.h msgid "Check the GPG signature of tags" msgstr "Verifica la signatura GPG de les etiquetes" +#: command-list.h msgid "Display version information about Git" msgstr "Mostra informació de la versió del Git" +#: command-list.h msgid "Show logs with differences each commit introduces" msgstr "Mostra els registres amb les diferències que introdueix cada comissió" +#: command-list.h msgid "Manage multiple working trees" msgstr "Gestiona múltiples arbres de treball" +#: command-list.h msgid "Create a tree object from the current index" msgstr "Crea un objecte arbre des de l'Ãndex actual" +#: command-list.h msgid "Defining attributes per path" msgstr "La definició d'atributs per camÃ" +#: command-list.h msgid "Git command-line interface and conventions" msgstr "InterfÃcie i convencions de la lÃnia d'ordres del Git" +#: command-list.h msgid "A Git core tutorial for developers" msgstr "Un tutorial bà sic del Git per a desenvolupadors" +#: command-list.h msgid "Providing usernames and passwords to Git" msgstr "Proporcionar noms d'usuari i contrasenyes a Git" +#: command-list.h msgid "Git for CVS users" msgstr "Git per a usuaris del CVS" +#: command-list.h msgid "Tweaking diff output" msgstr "Ajustament de la sortida de diferències" +#: command-list.h msgid "A useful minimum set of commands for Everyday Git" msgstr "Un conjunt mÃnim útil d'ordres dià ries del Git" +#: command-list.h msgid "Frequently asked questions about using Git" msgstr "Preguntes freqüents sobre l'ús del Git" +#: command-list.h msgid "The bundle file format" msgstr "El format del fitxer de farcell" +#: command-list.h msgid "Chunk-based file formats" msgstr "Formats de fitxer basats en blocs" +#: command-list.h msgid "Git commit-graph format" msgstr "Format de graf de comissions del Git" +#: command-list.h msgid "Git index format" msgstr "Format de l'Ãndex del Git" +#: command-list.h msgid "Git pack format" msgstr "format de paquet del Git" +#: command-list.h msgid "Git cryptographic signature formats" msgstr "Formats de signatura criptogrà fica del Git" +#: command-list.h msgid "A Git Glossary" msgstr "Un glossari de Git" +#: command-list.h msgid "Hooks used by Git" msgstr "Lligams utilitzats pel Git" +#: command-list.h msgid "Specifies intentionally untracked files to ignore" msgstr "Especifica els fitxers intencionalment no seguits a ignorar" +#: command-list.h msgid "The Git repository browser" msgstr "El navegador de repositoris Git" +#: command-list.h msgid "Map author/committer names and/or E-Mail addresses" msgstr "Assigna noms d'autor i comitent i/o adreces de correu electrònic" +#: command-list.h msgid "Defining submodule properties" msgstr "La definició de les propietats de submòduls" +#: command-list.h msgid "Git namespaces" msgstr "Espais de noms del Git" +#: command-list.h msgid "Protocol v0 and v1 capabilities" msgstr "Capacitats de protocol v0 i v1" +#: command-list.h msgid "Things common to various protocols" msgstr "Coses comunes en diversos protocols" +#: command-list.h msgid "Git HTTP-based protocols" msgstr "Protocols basats en HTTP del Git" +#: command-list.h msgid "How packs are transferred over-the-wire" msgstr "Com es transfereixen els paquets en la xarxa" +#: command-list.h msgid "Git Wire Protocol, Version 2" msgstr "Protocol Git Wire, versió 2" +#: command-list.h msgid "Helper programs to interact with remote repositories" msgstr "Programes d'ajuda per a interactuar amb repositoris remots" +#: command-list.h msgid "Git Repository Layout" msgstr "Disposició del repositori del Git" +#: command-list.h msgid "Specifying revisions and ranges for Git" msgstr "L'especificació de revisions i rangs per al Git" +#: command-list.h msgid "Mounting one repository inside another" msgstr "Muntant un repositori dins un altre" +#: command-list.h msgid "A tutorial introduction to Git" msgstr "Un tutorial d'introducció al Git" +#: command-list.h msgid "A tutorial introduction to Git: part two" msgstr "Un tutorial d'introducció al Git: segona part" +#: command-list.h msgid "Git web interface (web frontend to Git repositories)" msgstr "InterfÃcie web del Git (interfÃcie web pels repositoris Git)" +#: command-list.h msgid "An overview of recommended workflows with Git" msgstr "Una visió de conjunt de fluxos de treball recomanats amb Git" +#: command-list.h msgid "A tool for managing large Git repositories" msgstr "Una eina per a gestionar dipòsits Git grans" +#: commit-graph.c msgid "commit-graph file is too small" msgstr "el fitxer del graf de comissions és massa petit" +#: commit-graph.c msgid "commit-graph oid fanout chunk is wrong size" msgstr "" "el fragment de «fanout» de l'oid del graf de comissions és de mida incorrecta" +#: commit-graph.c msgid "commit-graph fanout values out of order" msgstr "valors de graf de comissions de «fanout» estan fora d'ordre" +#: commit-graph.c msgid "commit-graph OID lookup chunk is the wrong size" msgstr "el fragment de cerca OID és de mida incorrecta" +#: commit-graph.c msgid "commit-graph commit data chunk is wrong size" msgstr "el fragment de dades del graf de comissions és de mida incorrecta" +#: commit-graph.c msgid "commit-graph generations chunk is wrong size" msgstr "" "el fragment de les generacions del graf de comissions és de mida incorrecta" +#: commit-graph.c msgid "commit-graph changed-path index chunk is too small" msgstr "" "el fragment d'Ãndex del canvi del camà del graf de comissions és massa petit" +#: commit-graph.c #, c-format msgid "" "ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-" @@ -14675,107 +18711,144 @@ msgstr "" "s'ignorarà un fragment massa petit de camà canviat (%<PRIuMAX> < %<PRIuMAX>) " "al fitxer del graf de comissions" +#: commit-graph.c #, c-format msgid "commit-graph signature %X does not match signature %X" msgstr "" "la signatura del graf de comissions %X no coincideix amb la signatura %X" +#: commit-graph.c #, c-format msgid "commit-graph version %X does not match version %X" msgstr "la versió del graf de comissions %X no coincideix amb la versió %X" +#: commit-graph.c #, c-format msgid "commit-graph hash version %X does not match version %X" msgstr "" "la versió del resum del graf de comissions %X no coincideix amb la versió %X" +#: commit-graph.c #, c-format msgid "commit-graph file is too small to hold %u chunks" msgstr "" "el fitxer del graf de comissions és massa petit per a guardar %u fragments" +#: commit-graph.c msgid "commit-graph required OID fanout chunk missing or corrupted" msgstr "" "manca o està malmès el fragment del «fanout» OID requerit al graf de " "comissions" +#: commit-graph.c msgid "commit-graph required OID lookup chunk missing or corrupted" msgstr "" "manca o està malmès el fragment de cerca d'OID requerit al graf de comissions" +#: commit-graph.c msgid "commit-graph required commit data chunk missing or corrupted" msgstr "" "manca o està corromput el fragment de dades de publicació requerit al graf " "de comissions" +#: commit-graph.c +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"s'han inhabilitat els filtres de Bloom per a la capa del graf de comissions " +"«%s»\n" +"perquè els parà metres són incompatibles" + +#: commit-graph.c msgid "commit-graph has no base graphs chunk" msgstr "el fragment del graf de comissions no té grafs de base" +#: commit-graph.c msgid "commit-graph base graphs chunk is too small" msgstr "el fragment de grafs base de la grà fica de comissió és massa petit" +#: commit-graph.c msgid "commit-graph chain does not match" msgstr "la cadena del graf de comissions no coincideix" +#: commit-graph.c #, c-format msgid "commit count in base graph too high: %<PRIuMAX>" msgstr "el nombre de comissions en el graf base és massa alt: %<PRIuMAX>" +#: commit-graph.c msgid "commit-graph chain file too small" msgstr "el fitxer de cadena del graf de comissions és massa petit" +#: commit-graph.c #, c-format msgid "invalid commit-graph chain: line '%s' not a hash" msgstr "" "la cadena del graf de comissions no és và lida: la lÃnia «%s» no és un hash" +#: commit-graph.c msgid "unable to find all commit-graph files" msgstr "no es poden trobar tots els fitxers del graf de comissions" +#: commit-graph.c msgid "invalid commit position. commit-graph is likely corrupt" msgstr "" "posició de la comissió no và lida. Probablement el graf de comissions està " "malmès" +#: commit-graph.c #, c-format msgid "could not find commit %s" msgstr "no s'ha pogut trobar la comissió %s" +#: commit-graph.c msgid "commit-graph requires overflow generation data but has none" msgstr "" "el graf de comissions requereix dades de generació de desbordaments però no " "en té cap" +#: commit-graph.c msgid "commit-graph overflow generation data is too small" msgstr "" "les dades de generació de desbordament del graf de comissions són massa " "petites" +#: commit-graph.c msgid "commit-graph extra-edges pointer out of bounds" msgstr "punter de vores extra del graf de comissió està fora dels lÃmits" +#: commit-graph.c msgid "Loading known commits in commit graph" msgstr "S'estan carregant comissions conegudes al graf de comissions" +#: commit-graph.c msgid "Expanding reachable commits in commit graph" msgstr "S'estan expandint les comissions abastables al graf de comissions" +#: commit-graph.c msgid "Clearing commit marks in commit graph" msgstr "S'estan esborrant les marques de comissions al graf de comissions" +#: commit-graph.c msgid "Computing commit graph topological levels" msgstr "S'estan calculant els nivells topològics del graf de comissions" +#: commit-graph.c msgid "Computing commit graph generation numbers" msgstr "S'estan calculant els nombres de generació del graf de comissions" +#: commit-graph.c msgid "Computing commit changed paths Bloom filters" msgstr "" -"S'estan calculant els canvis les rutes de la comissió en els filtres Bloom" +"S'estan calculant els canvis les rutes de la comissió en els filtres de Bloom" +#: commit-graph.c msgid "Collecting referenced commits" msgstr "S'estan recollint els objectes referenciats" +#: commit-graph.c #, c-format msgid "Finding commits for commit graph in %<PRIuMAX> pack" msgid_plural "Finding commits for commit graph in %<PRIuMAX> packs" @@ -14784,128 +18857,166 @@ msgstr[0] "" msgstr[1] "" "S'estan cercant les comissions pel graf de comissions en %<PRIuMAX> paquets" +#: commit-graph.c #, c-format msgid "error adding pack %s" msgstr "error en afegir paquet %s" +#: commit-graph.c #, c-format msgid "error opening index for %s" msgstr "s'ha produït un error en obrir l'Ãndex per «%s»" +#: commit-graph.c msgid "Finding commits for commit graph among packed objects" msgstr "" "S'estan cercant les comissions pel graf de comissions entre els objectes " "empaquetats" +#: commit-graph.c msgid "Finding extra edges in commit graph" msgstr "S'estan cercant les vores addicionals al graf de comissions" +#: commit-graph.c msgid "failed to write correct number of base graph ids" msgstr "" "s'ha produït un error en escriure el nombre correcte d'ids base del graf" +#: commit-graph.c msgid "unable to create temporary graph layer" msgstr "no s'ha pogut crear una capa de graf temporal" +#: commit-graph.c midx-write.c #, c-format msgid "unable to adjust shared permissions for '%s'" msgstr "no s'han pogut ajustar els permisos compartits per a «%s»" +#: commit-graph.c #, c-format msgid "Writing out commit graph in %d pass" msgid_plural "Writing out commit graph in %d passes" msgstr[0] "S'està escrivint el graf de comissions en %d pas" msgstr[1] "S'està escrivint el graf de comissions en %d passos" +#: commit-graph.c msgid "unable to open commit-graph chain file" msgstr "no s'ha pogut obrir el fitxer d'encadenament del graf de comissions" +#: commit-graph.c msgid "failed to rename base commit-graph file" msgstr "no s'ha pogut canviar el nom del fitxer base del graf de comissions" +#: commit-graph.c msgid "failed to rename temporary commit-graph file" msgstr "" "no s'ha pogut canviar el nom del fitxer temporal del graf de comissions" +#: commit-graph.c #, c-format msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" msgstr "no es poden fusionar els grà fics amb %<PRIuMAX>, %<PRIuMAX>entregues" +#: commit-graph.c #, c-format msgid "cannot merge graph %s, too many commits: %<PRIuMAX>" msgstr "no es pot fusionar el graf %s, hi ha massa comissions: %<PRIuMAX>" +#: commit-graph.c msgid "Scanning merged commits" msgstr "S'estan escanejant les comissions fusionades" +#: commit-graph.c msgid "Merging commit-graph" msgstr "S'està fusionant el graf de comissions" +#: commit-graph.c msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "" "s'està intentant escriure un graf de comissions, però «core.commitGraph» " "està desactivat" +#: commit-graph.c +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph." +"changedPathsVersion' (%d) is not supported" +msgstr "" +"s'ha intentat escriure un graf de comissió, però no s'admet 'commitGraph." +"changedPathsVersion' (%d)" + +#: commit-graph.c msgid "too many commits to write graph" msgstr "massa comissions per a escriure un graf" +#: commit-graph.c msgid "the commit-graph file has incorrect checksum and is likely corrupt" msgstr "" "el fitxer commit-graph (graf de comissions) té una suma de verificació " "incorrecta i probablement és corrupte" +#: commit-graph.c #, c-format msgid "commit-graph has incorrect OID order: %s then %s" msgstr "el graf de comissions té una ordre OID incorrecta; %s llavors %s" +#: commit-graph.c #, c-format msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u" msgstr "" "el graf de comissions té un valor de «fanout» incorrecte: fanout[%d] = %u != " "%u" +#: commit-graph.c #, c-format msgid "failed to parse commit %s from commit-graph" msgstr "" "s'ha produït un error en analitzar la comissió %s del graf de comissions" +#: commit-graph.c #, c-format msgid "failed to parse commit %s from object database for commit-graph" msgstr "" "no s'han pogut analitzar la comissió %s de la base de dades d'objectes per " "al graf de comissions" +#: commit-graph.c #, c-format msgid "root tree OID for commit %s in commit-graph is %s != %s" msgstr "" "OID de l'arbre arrel per a comissions %s en el graf de comissions és %s != %s" +#: commit-graph.c #, c-format msgid "commit-graph parent list for commit %s is too long" msgstr "" "la llista de pares del graf de comissions per a la comissió %s és massa " "llarga" +#: commit-graph.c #, c-format msgid "commit-graph parent for %s is %s != %s" msgstr "el pare pel graf de comissions %s és %s != %s" +#: commit-graph.c #, c-format msgid "commit-graph parent list for commit %s terminates early" msgstr "la llista pare del graf de comissions per %s acaba aviat" +#: commit-graph.c #, c-format msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>" msgstr "" "generació del graf de comissions per a la comissió %s és %<PRIuMAX> < " "%<PRIuMAX>" +#: commit-graph.c #, c-format msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>" msgstr "" "la data d'enviament per a la comissió %s en el graf de comissions és " "%<PRIuMAX> != %<PRIuMAX>" +#: commit-graph.c #, c-format msgid "" "commit-graph has both zero and non-zero generations (e.g., commits '%s' and " @@ -14914,13 +19025,21 @@ msgstr "" "El graf de comissió té tant generacions zero com no nul·les (p. ex., " "comissions «%s» i «%s»)" +#: commit-graph.c msgid "Verifying commits in commit graph" msgstr "S'estan verificant les comissions al graf de comissions" +#: commit-reach.c sequencer.c +#, c-format +msgid "could not parse commit %s" +msgstr "no s'ha pogut analitzar la comissió %s" + +#: commit.c #, c-format msgid "%s %s is not a commit!" msgstr "%s %s no és una comissió!" +#: commit.c msgid "" "Support for <GIT_DIR>/info/grafts is deprecated\n" "and will be removed in a future Git version.\n" @@ -14940,28 +19059,34 @@ msgstr "" "Desactiveu aquest missatge executant\n" "«git config advice.graftFileDeprecated false»" +#: commit.c #, c-format msgid "commit %s exists in commit-graph but not in the object database" msgstr "" "la comissió %s existeix al graf de comissions però no a la base de dades " "d'objectes" +#: commit.c #, c-format msgid "Commit %s has an untrusted GPG signature, allegedly by %s." msgstr "La comissió %s té una signatura GPG no fiable, suposadament de %s." +#: commit.c #, c-format msgid "Commit %s has a bad GPG signature allegedly by %s." msgstr "La comissió %s té una signatura GPG incorrecta suposadament de %s." +#: commit.c #, c-format msgid "Commit %s does not have a GPG signature." msgstr "La comissió %s no té signatura GPG." +#: commit.c #, c-format msgid "Commit %s has a good GPG signature by %s\n" msgstr "La comissió %s té una signatura GPG bona de %s\n" +#: commit.c msgid "" "Warning: commit message did not conform to UTF-8.\n" "You may want to amend it after fixing the message, or set the config\n" @@ -14972,203 +19097,260 @@ msgstr "" "la variable de configuració i18n.commitencoding a la codificació que\n" "usi el vostre projecte.\n" +#: compat/compiler.h msgid "no compiler information available\n" msgstr "no hi ha informació disponible del compilador\n" +#: compat/compiler.h msgid "no libc information available\n" msgstr "no hi ha informació disponible de libc\n" +#: compat/disk.h #, c-format msgid "could not determine free disk size for '%s'" msgstr "no s'ha pogut determinar l'espai de disc lliure per a «%s»" +#: compat/disk.h #, c-format msgid "could not get info for '%s'" msgstr "no s'ha pogut obtenir la informació per a «%s»" +#: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "[GLE %ld] health thread could not open '%ls'" msgstr "[GLE %ld] el fil de salut no ha pogut obrir «%ls»" +#: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "[GLE %ld] health thread getting BHFI for '%ls'" msgstr "[GLE %ld] s'està obtenint BHFI del fil de salut per a «%ls»" +#: compat/fsmonitor/fsm-health-win32.c compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "could not convert to wide characters: '%s'" msgstr "no s'ha pogut convertir a carà cters amples: «%s»" +#: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "BHFI changed '%ls'" msgstr "S'ha canviat BHFI «%ls»" +#: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "unhandled case in 'has_worktree_moved': %d" msgstr "cas no gestionat a «has_worktree_moved»: %d" +#: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "health thread wait failed [GLE %ld]" msgstr "ha fallat l'espera del fil de salut [GLE %ld]" +#: compat/fsmonitor/fsm-ipc-darwin.c #, c-format msgid "Invalid path: %s" msgstr "Camà no và lid: «%s»" +#: compat/fsmonitor/fsm-listen-darwin.c msgid "Unable to create FSEventStream." msgstr "No s'ha pogut crear el FSEventStream." +#: compat/fsmonitor/fsm-listen-darwin.c msgid "Failed to start the FSEventStream" msgstr "No s'ha pogut iniciar el FSEventStream" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "[GLE %ld] could not convert path to UTF-8: '%.*ls'" msgstr "[GLE %ld] no s'ha pogut convertir el camà a UTF-8: «%.*ls»" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "[GLE %ld] could not watch '%s'" msgstr "[GLE %ld] no s'ha pogut vigilar «%s»" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "[GLE %ld] could not get longname of '%s'" msgstr "[GLE %ld] no s'ha pogut obtenir el nom llarg de «%s»" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "ReadDirectoryChangedW failed on '%s' [GLE %ld]" msgstr "Ha fallat ReadDirectoryChangedW a «%s» [GLE %ld]" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "GetOverlappedResult failed on '%s' [GLE %ld]" msgstr "Ha fallat GetOverlappedResult a «%s» [GLE %ld]" +#: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "could not read directory changes [GLE %ld]" msgstr "no s'han pogut llegir els canvis de directori [GLE %ld]" +#: compat/fsmonitor/fsm-path-utils-darwin.c #, c-format msgid "opendir('%s') failed" msgstr "ha fallat opendir(«%s»)" +#: compat/fsmonitor/fsm-path-utils-darwin.c #, c-format msgid "lstat('%s') failed" msgstr "ha fallat lstat(«%s»)" +#: compat/fsmonitor/fsm-path-utils-darwin.c #, c-format msgid "strbuf_readlink('%s') failed" msgstr "ha fallat strbuf_readlink(«%s»)" +#: compat/fsmonitor/fsm-path-utils-darwin.c #, c-format msgid "closedir('%s') failed" msgstr "ha fallat closedir(«%s»)" +#: compat/fsmonitor/fsm-path-utils-win32.c #, c-format msgid "[GLE %ld] unable to open for read '%ls'" msgstr "[GLE %ld] no s'ha pogut obrir per a llegir «%ls»" +#: compat/fsmonitor/fsm-path-utils-win32.c #, c-format msgid "[GLE %ld] unable to get protocol information for '%ls'" msgstr "[GLE %ld] no s'ha pogut obtenir la informació del protocol per a «%ls»" +#: compat/mingw.c #, c-format msgid "failed to copy SID (%ld)" msgstr "no s'ha pogut copiar el SID (%ld)" +#: compat/mingw.c #, c-format msgid "failed to get owner for '%s' (%ld)" msgstr "no s'ha pogut obtenir el propietari de «%s» (%ld)" +#: compat/obstack.c msgid "memory exhausted" msgstr "memòria esgotada" +#: compat/regex/regcomp.c msgid "Success" msgstr "Èxit" +#: compat/regex/regcomp.c msgid "No match" msgstr "Cap coincidència" +#: compat/regex/regcomp.c msgid "Invalid regular expression" msgstr "Expressió regular no và lida" +#: compat/regex/regcomp.c msgid "Invalid collation character" msgstr "El carà cter de col·lació no és và lid" +#: compat/regex/regcomp.c msgid "Invalid character class name" msgstr "Nom de la classe del carà cter no và lid" +#: compat/regex/regcomp.c msgid "Trailing backslash" msgstr "Barra inversa del final" +#: compat/regex/regcomp.c msgid "Invalid back reference" msgstr "Referència anterior no và lida" +#: compat/regex/regcomp.c msgid "Unmatched [ or [^" msgstr "[ o [^ no emparellat" +#: compat/regex/regcomp.c msgid "Unmatched ( or \\(" msgstr "( o \\( no emparellat" +#: compat/regex/regcomp.c msgid "Unmatched \\{" msgstr "\\{ no emparellat" +#: compat/regex/regcomp.c msgid "Invalid content of \\{\\}" msgstr "Contingut no và lid de \\{\\}" +#: compat/regex/regcomp.c msgid "Invalid range end" msgstr "Fi d'interval no và lid" +#: compat/regex/regcomp.c msgid "Memory exhausted" msgstr "Memòria esgotada" +#: compat/regex/regcomp.c msgid "Invalid preceding regular expression" msgstr "Expressió regular anterior no và lida" +#: compat/regex/regcomp.c msgid "Premature end of regular expression" msgstr "Fi prematur d'expressió regular" +#: compat/regex/regcomp.c msgid "Regular expression too big" msgstr "Expressió regular és massa gran" +#: compat/regex/regcomp.c msgid "Unmatched ) or \\)" msgstr ") o \\) no emparellat" +#: compat/regex/regcomp.c msgid "No previous regular expression" msgstr "No hi ha expressió regular anterior" +#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c msgid "could not send IPC command" msgstr "no s'ha pogut enviar l'ordre IPC" +#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c msgid "could not read IPC response" msgstr "no s'ha pogut llegir la resposta IPC" +#: compat/simple-ipc/ipc-unix-socket.c #, c-format msgid "could not start accept_thread '%s'" msgstr "no s'ha pogut començar un fil «accept_thread» «%s»" +#: compat/simple-ipc/ipc-unix-socket.c #, c-format msgid "could not start worker[0] for '%s'" msgstr "no s'ha pogut iniciar el fil[0] per a «%s»" +#: compat/simple-ipc/ipc-win32.c #, c-format msgid "ConnectNamedPipe failed for '%s' (%lu)" msgstr "Ha fallat ConnectNamedPipe per a «%s» (%lu)" +#: compat/simple-ipc/ipc-win32.c #, c-format msgid "could not create fd from pipe for '%s'" msgstr "no s'ha pogut crear un fd a partir de la canonada per a «%s»" +#: compat/simple-ipc/ipc-win32.c #, c-format msgid "could not start thread[0] for '%s'" msgstr "no s'ha pogut iniciar el fil[0] per a «%s»" +#: compat/simple-ipc/ipc-win32.c #, c-format msgid "wait for hEvent failed for '%s'" msgstr "ha fallat l'espera de hEvent per a «%s»" +#: compat/terminal.c msgid "cannot resume in the background, please use 'fg' to resume" msgstr "no es pot reprendre en segon pla, si us plau useu «fg» per a reprendre" +#: compat/terminal.c msgid "cannot restore terminal settings" msgstr "no es poden restaurar els parà metres del terminal" +#: config.c #, c-format msgid "" "exceeded maximum include depth (%d) while including\n" @@ -15183,17 +19365,21 @@ msgstr "" "\t%s\n" "Això pot ser degut a inclusions circulars." +#: config.c #, c-format msgid "could not expand include path '%s'" msgstr "no s'ha pogut expandir el camà d'inclusió «%s»" +#: config.c msgid "relative config includes must come from files" msgstr "les inclusions de configuració relatives han de venir de fitxers" +#: config.c msgid "relative config include conditionals must come from files" msgstr "" "els condicionals d'inclusió de configuració relatius han de venir de fitxers" +#: config.c msgid "" "remote URLs cannot be configured in file directly or indirectly included by " "includeIf.hasconfig:remote.*.url" @@ -15201,273 +19387,353 @@ msgstr "" "URL remots no es poden configurar en un fitxer directament o indirectament " "inclòs per «includeIf.hasconfig:remote.*.url»" +#: config.c #, c-format msgid "invalid config format: %s" msgstr "format de configuració no và lid: %s" +#: config.c #, c-format msgid "missing environment variable name for configuration '%.*s'" msgstr "falta el nom de la variable d'entorn per a la configuració «%.*s»" +#: config.c #, c-format msgid "missing environment variable '%s' for configuration '%.*s'" msgstr "falta la variable d'entorn «%s» per a la configuració «%.*s»" +#: config.c #, c-format msgid "key does not contain a section: %s" msgstr "la clau no conté una secció: «%s»" +#: config.c #, c-format msgid "key does not contain variable name: %s" msgstr "la clau no conté un nom de variable: «%s»" +#: config.c sequencer.c #, c-format msgid "invalid key: %s" msgstr "clau no và lida: %s" +#: config.c #, c-format msgid "invalid key (newline): %s" msgstr "clau no và lida (lÃnia nova): %s" +#: config.c msgid "empty config key" msgstr "clau de configuració buida" +#: config.c #, c-format msgid "bogus config parameter: %s" msgstr "parà metre de configuració erroni: %s" +#: config.c #, c-format msgid "bogus format in %s" msgstr "format erroni a %s" +#: config.c #, c-format msgid "bogus count in %s" msgstr "comptatge erroni a %s" +#: config.c #, c-format msgid "too many entries in %s" msgstr "hi ha massa arguments a %s" +#: config.c #, c-format msgid "missing config key %s" msgstr "falta la clau de configuració %s" +#: config.c #, c-format msgid "missing config value %s" msgstr "falta el valor de configuració %s" +#: config.c #, c-format msgid "bad config line %d in blob %s" msgstr "lÃnia de configuració %d errònia en el blob %s" +#: config.c #, c-format msgid "bad config line %d in file %s" msgstr "lÃnia de configuració %d errònia en el fitxer %s" +#: config.c #, c-format msgid "bad config line %d in standard input" msgstr "lÃnia de configuració %d errònia en l'entrada està ndard" +#: config.c #, c-format msgid "bad config line %d in submodule-blob %s" msgstr "lÃnia de configuració %d errònia en el blob de submòdul %s" +#: config.c #, c-format msgid "bad config line %d in command line %s" msgstr "lÃnia de configuració %d errònia en la lÃnia d'ordres %s" +#: config.c #, c-format msgid "bad config line %d in %s" msgstr "lÃnia de configuració %d errònia en %s" +#: config.c msgid "out of range" msgstr "fora de rang" +#: config.c msgid "invalid unit" msgstr "unitat no và lida" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s': %s" msgstr "valor de configuració numèric erroni «%s» per «%s»: %s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in blob %s: %s" msgstr "valor de configuració numèric erroni «%s» per «%s» en el blob %s: %s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in file %s: %s" msgstr "valor de configuració numèric «%s» erroni per «%s» en el fitxer %s: %s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in standard input: %s" msgstr "" "valor de configuració numèric «%s» erroni per «%s» en l'entrada està ndard: %s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s" msgstr "" "valor de configuració numèric «%s» erroni per «%s» en el blob de submòdul " "%s: %s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in command line %s: %s" msgstr "" "valor de configuració numèric «%s» erroni per «%s» en la lÃnia d'ordres %s: " "%s" +#: config.c #, c-format msgid "bad numeric config value '%s' for '%s' in %s: %s" msgstr "valor de configuració numèric incorrecte «%s» per «%s» en %s: %s" +#: config.c #, c-format msgid "invalid value for variable %s" msgstr "valor no và lid per a la variable %s" +#: config.c #, c-format msgid "ignoring unknown core.fsync component '%s'" msgstr "s'ignora el component core.fsync «%s» desconegut" +#: config.c #, c-format msgid "bad boolean config value '%s' for '%s'" msgstr "valor de configuració booleà erroni «%s» per a «%s»" +#: config.c #, c-format msgid "failed to expand user dir in: '%s'" msgstr "s'ha produït un error en expandir el directori d'usuari en: «%s»" +#: config.c #, c-format msgid "'%s' for '%s' is not a valid timestamp" msgstr "«%s» per a «%s» no és una marca de temps và lida" +#: config.c #, c-format msgid "abbrev length out of range: %d" msgstr "la longitud d'«abbrev» està fora de rang: %d" +#: config.c #, c-format msgid "bad zlib compression level %d" msgstr "nivell de compressió de zlib incorrecte %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar només hauria de ser un carà cter ASCII" +# newline → lÃnia nova o salt de lÃnia? +#: config.c +#, c-format +msgid "%s cannot contain newline" +msgstr "%s no pot contenir una nova lÃnia" + +#: config.c +#, c-format +msgid "%s must have at least one character" +msgstr "%s ha de tenir almenys un carà cter" +#: config.c #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" msgstr "s'ignora el valor desconegut «%s» de core.fsyncMethod" +#: config.c msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead" msgstr "core.fsyncObjectFiles és obsolet; useu core.fsync" +#: config.c #, c-format msgid "invalid mode for object creation: %s" msgstr "mode de creació d'objecte no và lid: %s" +#: config.c #, c-format msgid "malformed value for %s" msgstr "valor no và lid per a %s" +#: config.c #, c-format msgid "malformed value for %s: %s" msgstr "valor no và lid per a %s: %s" +#: config.c msgid "must be one of nothing, matching, simple, upstream or current" msgstr "" "ha de ser un dels elements següents: nothing, matching, simple, upstream o " "current" +#: config.c #, c-format msgid "unable to load config blob object '%s'" msgstr "no s'ha pogut carregar l'objecte blob de configuració «%s»" +#: config.c #, c-format msgid "reference '%s' does not point to a blob" msgstr "la referència «%s» no assenyala a un blob" +#: config.c #, c-format msgid "unable to resolve config blob '%s'" msgstr "no s'ha pogut resoldre el blob de configuració: «%s»" +#: config.c msgid "unable to parse command-line config" msgstr "no s'ha pogut analitzar la configuració de la lÃnia d'ordres" +#: config.c msgid "unknown error occurred while reading the configuration files" msgstr "un error desconegut ha ocorregut en llegir els fitxers de configuració" +#: config.c #, c-format msgid "Invalid %s: '%s'" msgstr "%s no và lid: «%s»" +#: config.c #, c-format msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100" msgstr "valor «%d» a splitIndex.maxPercentChange ha d'estar entre 0 i 100" +#: config.c #, c-format msgid "unable to parse '%s' from command-line config" msgstr "no s'ha pogut analitzar «%s» de la configuració de la lÃnia d'ordres" +#: config.c #, c-format msgid "bad config variable '%s' in file '%s' at line %d" msgstr "variable de configuració «%s» errònia en el fitxer «%s» a la lÃnia %d" +#: config.c #, c-format msgid "invalid section name '%s'" msgstr "nom de secció no và lid «%s»" +#: config.c #, c-format msgid "%s has multiple values" msgstr "%s té múltiples valors" +#: config.c #, c-format msgid "failed to write new configuration file %s" msgstr "no es pot escriure un nou fitxer de configuració %s" +#: config.c +#, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "no es permet el comentari multi-lÃnia: «%s»" + +#: config.c #, c-format msgid "could not lock config file %s" msgstr "no s'ha pogut blocar el fitxer de configuració %s" +#: config.c #, c-format msgid "opening %s" msgstr "s'està obrint %s" +#: config.c #, c-format msgid "invalid config file %s" msgstr "fitxer de configuració no và lid %s" +#: config.c #, c-format msgid "fstat on %s failed" msgstr "ha fallat «fstat» a %s" +#: config.c #, c-format msgid "unable to mmap '%s'%s" msgstr "no s'ha pogut fer «mmap» «%s»%s" +#: config.c #, c-format msgid "chmod on %s failed" msgstr "ha fallat chmod a %s" +#: config.c #, c-format msgid "could not write config file %s" msgstr "no s'ha pogut escriure el fitxer de configuració «%s»" +#: config.c #, c-format msgid "could not set '%s' to '%s'" msgstr "no s'ha pogut establir «%s» a «%s»" +#: config.c #, c-format msgid "invalid section name: %s" msgstr "nom de secció no và lida: %s" +#: config.c #, c-format msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>" msgstr "" "es rebutja treballar amb una lÃnia massa llarga a «%s» a la lÃnia %<PRIuMAX>" +#: config.c #, c-format msgid "missing value for '%s'" msgstr "falta el valor per «%s»" +#: connect.c msgid "the remote end hung up upon initial contact" msgstr "el costat remot ha penjat en el moment de contacte inicial" +#: connect.c msgid "" "Could not read from remote repository.\n" "\n" @@ -15479,77 +19745,97 @@ msgstr "" "Assegureu-vos que tingueu els permisos\n" "d'accés correctes i que el repositori existeixi." +#: connect.c #, c-format msgid "server doesn't support '%s'" msgstr "el servidor no és compatible amb «%s»" +#: connect.c #, c-format msgid "server doesn't support feature '%s'" msgstr "el servidor no és compatible amb la caracterÃstica «%s»" +#: connect.c msgid "expected flush after capabilities" msgstr "s'esperava un buidatge després de les capacitats" +#: connect.c #, c-format msgid "ignoring capabilities after first line '%s'" msgstr "ignora les capacitats després de la primera lÃnia «%s»" +#: connect.c msgid "protocol error: unexpected capabilities^{}" msgstr "error de protocol: unexpected capabilities^{}" +#: connect.c #, c-format msgid "protocol error: expected shallow sha-1, got '%s'" msgstr "" "s'ha produït un error de protocol: s'esperava shallow sha-1, s'ha rebut «%s»" +#: connect.c msgid "repository on the other end cannot be shallow" msgstr "el repositori de l'altre extrem no pot ser shallow" +#: connect.c msgid "invalid packet" msgstr "paquet no và lid" +#: connect.c #, c-format msgid "protocol error: unexpected '%s'" msgstr "s'ha produït un error de protocol: no s'esperava «%s»" +#: connect.c #, c-format msgid "unknown object format '%s' specified by server" msgstr "format d'objecte «%s» especificat pel servidor desconegut" +#: connect.c #, c-format msgid "error on bundle-uri response line %d: %s" msgstr "error a la lÃnia de resposta de bundle-uri %d: %s" +#: connect.c msgid "expected flush after bundle-uri listing" msgstr "s'esperava un buidatge després del llistat de bundle-uri" +#: connect.c msgid "expected response end packet after ref listing" msgstr "" "s'esperava un paquet de final de resposta després del llistat de referències" +#: connect.c #, c-format msgid "invalid ls-refs response: %s" msgstr "resposta de ls-refs no và lida: %s" +#: connect.c msgid "expected flush after ref listing" msgstr "s'esperava una neteja després del llistat de referències" +#: connect.c #, c-format msgid "protocol '%s' is not supported" msgstr "el protocol «%s» no és compatible" +#: connect.c msgid "unable to set SO_KEEPALIVE on socket" msgstr "no s'ha pogut establir SO_KEEPALIVE al sòcol" +#: connect.c #, c-format msgid "Looking up %s ... " msgstr "S'està cercant %s..." +#: connect.c #, c-format msgid "unable to look up %s (port %s) (%s)" msgstr "no s'ha pogut trobar %s (port %s) (%s)" #. TRANSLATORS: this is the end of "Looking up %s ... " +#: connect.c #, c-format msgid "" "done.\n" @@ -15558,6 +19844,7 @@ msgstr "" "fet.\n" "S'està connectant a %s (port %s) ... " +#: connect.c #, c-format msgid "" "unable to connect to %s:\n" @@ -15567,72 +19854,91 @@ msgstr "" "%s" #. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... " +#: connect.c msgid "done." msgstr "fet." +#: connect.c #, c-format msgid "unable to look up %s (%s)" msgstr "no s'ha pogut trobar %s (%s)" +#: connect.c #, c-format msgid "unknown port %s" msgstr "port desconegut %s" +#: connect.c #, c-format msgid "strange hostname '%s' blocked" msgstr "s'ha bloquejat el nom estrany d'amfitrió «%s»" +#: connect.c #, c-format msgid "strange port '%s' blocked" msgstr "s'ha bloquejat el port estrany «%s»" +#: connect.c #, c-format msgid "cannot start proxy %s" msgstr "no s'ha pogut iniciar servidor intermediari «%s»" +#: connect.c msgid "no path specified; see 'git help pull' for valid url syntax" msgstr "" "no s'ha especificat un camÃ; vegeu «git help pull» per la sintaxi và lida per " "URL" +#: connect.c msgid "newline is forbidden in git:// hosts and repo paths" msgstr "" "la lÃnia nova està prohibida en els servidors git:// i els camins de " "repositori" +#: connect.c msgid "ssh variant 'simple' does not support -4" msgstr "la variant «simple» de ssh no és compatible amb -4" +#: connect.c msgid "ssh variant 'simple' does not support -6" msgstr "la variant «simple» de ssh no és compatible amb -6" +#: connect.c msgid "ssh variant 'simple' does not support setting port" msgstr "la variant «simple» de ssh no permet definir el port" +#: connect.c #, c-format msgid "strange pathname '%s' blocked" msgstr "s'ha bloquejat el nom de fitxer estrany «%s»" +#: connect.c msgid "unable to fork" msgstr "no s'ha pogut bifurcar" +#: connected.c msgid "Could not run 'git rev-list'" msgstr "No s'ha pogut executar «git rev-list»" +#: connected.c msgid "failed write to rev-list" msgstr "escriptura fallada al rev-list" +#: connected.c msgid "failed to close rev-list's stdin" msgstr "s'ha produït un error en tancar l'stdin del rev-list" +#: convert.c #, c-format msgid "illegal crlf_action %d" msgstr "crlf_action %d il·legal" +#: convert.c #, c-format msgid "CRLF would be replaced by LF in %s" msgstr "CRLF es reemplaçà per LF en %s" +#: convert.c #, c-format msgid "" "in the working copy of '%s', CRLF will be replaced by LF the next time Git " @@ -15641,10 +19947,12 @@ msgstr "" "a la còpia de treball de «%s», CRLF serà substituït per LF, la propera " "vegada que el Git ho modifiqui" +#: convert.c #, c-format msgid "LF would be replaced by CRLF in %s" msgstr "LF es reemplaçà per CRLF en %s" +#: convert.c #, c-format msgid "" "in the working copy of '%s', LF will be replaced by CRLF the next time Git " @@ -15653,64 +19961,79 @@ msgstr "" "a la còpia de treball de «%s», LF serà substituït per CRLF la propera vegada " "que Git ho modifiqui" +#: convert.c #, c-format msgid "BOM is prohibited in '%s' if encoded as %s" msgstr "BOM està prohibida a «%s» si està codificada com a %s" +#: convert.c #, c-format msgid "" "The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as " "working-tree-encoding." msgstr "" -"El fitxer «%s» conté una marca d'ordre de byte (BOM). Utilitzeu UTF-%.*s com " -"a codificacions d'arbre de treball." +"El fitxer «%s» conté una marca d'ordre de octets (BOM). Utilitzeu UTF-%.*s " +"com a codificacions d'arbre de treball." +#: convert.c #, c-format msgid "BOM is required in '%s' if encoded as %s" msgstr "La BOM és necessà ria en «%s» si està codificada com a %s" +#: convert.c #, c-format msgid "" "The file '%s' is missing a byte order mark (BOM). Please use UTF-%sBE or UTF-" "%sLE (depending on the byte order) as working-tree-encoding." msgstr "" -"Falta una marca d'ordre de byte (BOM) al fitxer «%s». Useu UTF-%sBE o UTF-" -"%sLE (depenent de l'ordre de byte) com a codificacions d'arbre de treball." +"Falta una marca d'ordre d'octets (BOM) al fitxer «%s». Useu UTF-%sBE o UTF-" +"%sLE (depenent de l'ordre dels octets) com a codificacions d'arbre de " +"treball." +#: convert.c #, c-format msgid "failed to encode '%s' from %s to %s" msgstr "s'ha produït un error en codificar «%s» des de %s a %s" +#: convert.c #, c-format msgid "encoding '%s' from %s to %s and back is not the same" msgstr "codificar «%s» des de %s a %s i cap enrere no és el mateix" +#: convert.c #, c-format msgid "cannot fork to run external filter '%s'" msgstr "no es pot bifurcar per a executar el filtre extern «%s»" +#: convert.c #, c-format msgid "cannot feed the input to external filter '%s'" msgstr "no es pot alimentar l'entrada al filtre extern «%s»" +#: convert.c #, c-format msgid "external filter '%s' failed %d" msgstr "el filtre extern «%s» ha fallat %d" +#: convert.c #, c-format msgid "read from external filter '%s' failed" msgstr "la lectura del filtre extern «%s» ha fallat" +#: convert.c #, c-format msgid "external filter '%s' failed" msgstr "el filtre extern «%s» ha fallat" +#: convert.c msgid "unexpected filter type" msgstr "tipus de filtre inesperat" +#: convert.c msgid "path name too long for external filter" msgstr "el nom del camà és massa gran per al filtre extern" +#: convert.c #, c-format msgid "" "external filter '%s' is not available anymore although not all paths have " @@ -15719,80 +20042,97 @@ msgstr "" "el filtre extern «%s» ja no està disponible encara que no s'han filtrat tots " "els camins" +#: convert.c msgid "true/false are no valid working-tree-encodings" msgstr "cert/fals no són codificacions d'arbre de treball và lides" +#: convert.c #, c-format msgid "%s: clean filter '%s' failed" msgstr "%s: el filtre de netejat «%s» ha fallat" +#: convert.c #, c-format msgid "%s: smudge filter %s failed" msgstr "%s: ha fallat el filtre smudge %s" +#: credential.c #, c-format msgid "skipping credential lookup for key: credential.%s" msgstr "s'està ometent la cerca de credencials per una clau: credential.%s" +#: credential.c msgid "refusing to work with credential missing host field" msgstr "" "s'ha rebutjat treballar amb credencials que no tenen el camp d'amfitrió" +#: credential.c msgid "refusing to work with credential missing protocol field" msgstr "" "s'ha rebutjat treballar amb credencials que no tenen el camp de protocol" +#: credential.c #, c-format msgid "url contains a newline in its %s component: %s" msgstr "url conté una lÃnia nova en %s component: %s" +#: credential.c #, c-format msgid "url has no scheme: %s" msgstr "l'url no té esquema: %s" +#: credential.c #, c-format msgid "credential url cannot be parsed: %s" msgstr "no s'ha pogut analitzar l'URL de credencials: %s" +#: date.c msgid "in the future" msgstr "en el futur" +#: date.c #, c-format msgid "%<PRIuMAX> second ago" msgid_plural "%<PRIuMAX> seconds ago" msgstr[0] "fa %<PRIuMAX> segon" msgstr[1] "fa %<PRIuMAX> segons" +#: date.c #, c-format msgid "%<PRIuMAX> minute ago" msgid_plural "%<PRIuMAX> minutes ago" msgstr[0] "fa %<PRIuMAX> minut" msgstr[1] "fa %<PRIuMAX> minuts" +#: date.c #, c-format msgid "%<PRIuMAX> hour ago" msgid_plural "%<PRIuMAX> hours ago" msgstr[0] "fa %<PRIuMAX> hora" msgstr[1] "fa %<PRIuMAX> hores" +#: date.c #, c-format msgid "%<PRIuMAX> day ago" msgid_plural "%<PRIuMAX> days ago" msgstr[0] "fa %<PRIuMAX> dia" msgstr[1] "fa %<PRIuMAX> dies" +#: date.c #, c-format msgid "%<PRIuMAX> week ago" msgid_plural "%<PRIuMAX> weeks ago" msgstr[0] "fa %<PRIuMAX> setmana" msgstr[1] "fa %<PRIuMAX> setmanes" +#: date.c #, c-format msgid "%<PRIuMAX> month ago" msgid_plural "%<PRIuMAX> months ago" msgstr[0] "fa %<PRIuMAX> mes" msgstr[1] "fa %<PRIuMAX> mesos" +#: date.c #, c-format msgid "%<PRIuMAX> year" msgid_plural "%<PRIuMAX> years" @@ -15800,87 +20140,109 @@ msgstr[0] "%<PRIuMAX> any" msgstr[1] "%<PRIuMAX> anys" #. TRANSLATORS: "%s" is "<n> years" +#: date.c #, c-format msgid "%s, %<PRIuMAX> month ago" msgid_plural "%s, %<PRIuMAX> months ago" msgstr[0] "fa %s i %<PRIuMAX> mes" msgstr[1] "fa %s i %<PRIuMAX> mesos" +#: date.c #, c-format msgid "%<PRIuMAX> year ago" msgid_plural "%<PRIuMAX> years ago" msgstr[0] "fa %<PRIuMAX> any" msgstr[1] "fa %<PRIuMAX> anys" +#: delta-islands.c msgid "Propagating island marks" msgstr "S'estan propagant les marques d'illa" +#: delta-islands.c #, c-format msgid "bad tree object %s" msgstr "objecte d'arbre malmès %s" +#: delta-islands.c #, c-format msgid "failed to load island regex for '%s': %s" msgstr "" "s'ha produït un error en carregar l'expressió regular de l'illa per «%s»: %s" +#: delta-islands.c #, c-format msgid "island regex from config has too many capture groups (max=%d)" msgstr "" "l'expressió regular de l'illa des de la configuració té massa grups de " "captura (mà x=%d)" +#: delta-islands.c #, c-format msgid "Marked %d islands, done.\n" msgstr "Marcades %d illes, fet.\n" +#: diagnose.c #, c-format msgid "invalid --%s value '%s'" msgstr "no és và lid --%s amb valor «%s»" +#: diagnose.c #, c-format msgid "could not archive missing directory '%s'" msgstr "no s'ha pogut arxivar el directori que falta «%s»" +#: diagnose.c dir.c #, c-format msgid "could not open directory '%s'" msgstr "no s'ha pogut obrir el directori «%s»" +#: diagnose.c #, c-format msgid "skipping '%s', which is neither file nor directory" msgstr "s'omet «%s», que no és ni fitxer ni directori" +#: diagnose.c msgid "could not duplicate stdout" msgstr "no s'ha pogut duplicar stdout" +#: diagnose.c #, c-format msgid "could not add directory '%s' to archiver" msgstr "no s'ha pogut afegir el directori «%s» a l'arxivador" +#: diagnose.c msgid "failed to write archive" msgstr "s'ha produït un error en escriure arxiu" +#: diff-lib.c msgid "--merge-base does not work with ranges" msgstr "--merge-base no funciona amb intervals" +#: diff-lib.c msgid "unable to get HEAD" msgstr "no s'ha pogut obtenir HEAD" +#: diff-lib.c msgid "no merge base found" msgstr "no s'ha trobat una base de fusió" +#: diff-lib.c msgid "multiple merge bases found" msgstr "s'han trobat múltiples bases de fusió" +#: diff-no-index.c msgid "cannot compare stdin to a directory" msgstr "no es pot comparar stdin amb un directori" +#: diff-no-index.c msgid "cannot compare a named pipe to a directory" msgstr "no es pot comparar una canonada amb nom amb un directori" +#: diff-no-index.c msgid "git diff --no-index [<options>] <path> <path>" msgstr "git diff --no-index [<opcions>] <camÃ> <camÃ>" +#: diff-no-index.c msgid "" "Not a git repository. Use --no-index to compare two paths outside a working " "tree" @@ -15888,16 +20250,19 @@ msgstr "" "No és un repositori Git. Useu --no-index per a comparar dos camins fora del " "directori de treball" +#: diff.c #, c-format msgid " Failed to parse dirstat cut-off percentage '%s'\n" msgstr "" " S'ha produït un error en analitzar el percentatge limitant de dirstat " "«%s»\n" +#: diff.c #, c-format msgid " Unknown dirstat parameter '%s'\n" msgstr " Parà metre de dirstat desconegut «%s»\n" +#: diff.c msgid "" "color moved setting must be one of 'no', 'default', 'blocks', 'zebra', " "'dimmed-zebra', 'plain'" @@ -15905,6 +20270,7 @@ msgstr "" "el parà metre de color en moviment ha de ser «no», «default», «blocks», " "«zebra», «dimmed-zebra» o «plain»" +#: diff.c #, c-format msgid "" "unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', " @@ -15914,6 +20280,7 @@ msgstr "" "«ignore-space-change», «ignore-space-at-eol», «ignore-all-space», «allow-" "indentation-change»" +#: diff.c msgid "" "color-moved-ws: allow-indentation-change cannot be combined with other " "whitespace modes" @@ -15921,15 +20288,18 @@ msgstr "" "color-moved-ws: allow-indentation-change no es pot combinar amb altres modes " "d'espai en blanc" +#: diff.c #, c-format msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "" "Valor desconegut de la variable de configuració de «diff.submodule»: «%s»" +#: diff.c merge-recursive.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "valor desconegut per al config «%s»': %s" +#: diff.c #, c-format msgid "" "Found errors in 'diff.dirstat' config variable:\n" @@ -15938,39 +20308,48 @@ msgstr "" "S'han trobat errors en la variable de configuració «diff.dirstat»:\n" "%s" +#: diff.c #, c-format msgid "external diff died, stopping at %s" msgstr "el diff external s'ha mort, s'està aturant a %s" +#: diff.c msgid "--follow requires exactly one pathspec" msgstr "--follow requereix exactament una especificació de camÃ" +#: diff.c #, c-format msgid "pathspec magic not supported by --follow: %s" msgstr "el «pathspec» mà gic no està suportat per --follow: %s" +#: diff.c parse-options.c #, c-format msgid "options '%s', '%s', '%s', and '%s' cannot be used together" msgstr "les opcions «%s», «%s», «%s», i «%s» no es poden usar juntes" +#: diff.c #, c-format msgid "options '%s' and '%s' cannot be used together, use '%s' with '%s'" msgstr "les opcions «%s» i «%s» no es poden usar juntes, useu «%s» amb «%s»" +#: diff.c #, c-format msgid "" "options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'" msgstr "" "les opcions «%s» i «%s» no es poden usar juntes, useu «%s» amb «%s» i «%s»" +#: diff.c #, c-format msgid "invalid --stat value: %s" msgstr "valor --stat no và lid: %s" +#: diff.c parse-options.c #, c-format msgid "%s expects a numerical value" msgstr "%s espera un valor numèric" +#: diff.c #, c-format msgid "" "Failed to parse --dirstat/-X option parameter:\n" @@ -15979,147 +20358,189 @@ msgstr "" "S'ha produït un error en analitzar el parà metre d'opció de --dirstat/-X:\n" "%s" +#: diff.c #, c-format msgid "unknown change class '%c' in --diff-filter=%s" msgstr "classe de canvi «%c» desconeguda a --diff-filter=%s" +#: diff.c #, c-format msgid "unknown value after ws-error-highlight=%.*s" msgstr "valor desconegut després de ws-error-highlight=%.*s" +#: diff.c #, c-format msgid "unable to resolve '%s'" msgstr "no s'ha pogut resoldre «%s»" +#: diff.c #, c-format msgid "%s expects <n>/<m> form" msgstr "%s espera una forma <n>/<m>" +#: diff.c #, c-format msgid "%s expects a character, got '%s'" msgstr "%s esperava un carà cter, s'ha rebut «%s»" +#: diff.c #, c-format msgid "bad --color-moved argument: %s" msgstr "argument --color-moved incorrecte: %s" +#: diff.c #, c-format msgid "invalid mode '%s' in --color-moved-ws" msgstr "mode «%s» no và lid en --color-moved-ws" +#: diff.c #, c-format msgid "invalid argument to %s" msgstr "argument no và lid a %s" +#: diff.c #, c-format msgid "invalid regex given to -I: '%s'" msgstr "expressió regular donada a -I: no và lida: «%s»" +#: diff.c #, c-format msgid "failed to parse --submodule option parameter: '%s'" msgstr "" "s'ha produït un error en analitzar el parà metre d'opció de --submodule: «%s»" +#: diff.c #, c-format msgid "bad --word-diff argument: %s" msgstr "argument --word-diff incorrecte: %s" +#: diff.c msgid "Diff output format options" msgstr "Opcions del format de sortida del diff" +#: diff.c msgid "generate patch" msgstr "genera el pedaç" +#: diff.c msgid "<n>" msgstr "<n>" +#: diff.c msgid "generate diffs with <n> lines context" msgstr "genera diffs amb <n> lÃnies de context" +#: diff.c msgid "generate the diff in raw format" msgstr "genera el diff en format cru" +#: diff.c msgid "synonym for '-p --raw'" msgstr "sinònim de «-p --raw»" +#: diff.c msgid "synonym for '-p --stat'" msgstr "sinònim de «-p --stat»" +#: diff.c msgid "machine friendly --stat" msgstr "llegible per una mà quina --stat" +#: diff.c msgid "output only the last line of --stat" msgstr "mostra només l'última lÃnia de --stat" +#: diff.c msgid "<param1>,<param2>..." msgstr "<param1>,<param2>..." +#: diff.c msgid "" "output the distribution of relative amount of changes for each sub-directory" msgstr "" "genera la distribució de la quantitat relativa de canvis per a cada " "subdirectori" +#: diff.c msgid "synonym for --dirstat=cumulative" msgstr "sinònim de --dirstat=cumulative" +#: diff.c msgid "synonym for --dirstat=files,<param1>,<param2>..." msgstr "sinònim de --dirstat=files,<param1>,<param2>..." +#: diff.c msgid "warn if changes introduce conflict markers or whitespace errors" msgstr "" "avisa si els canvis introdueixen marcadors en conflicte o errors d'espai en " "blanc" +#: diff.c msgid "condensed summary such as creations, renames and mode changes" msgstr "resum condensat com ara creacions, canvis de nom i mode" +#: diff.c msgid "show only names of changed files" msgstr "mostra només els noms de fitxers canviats" +#: diff.c msgid "show only names and status of changed files" msgstr "mostra només els noms i l'estat dels fitxers canviats" +#: diff.c msgid "<width>[,<name-width>[,<count>]]" msgstr "<amplada>[<amplada-nom>[,<recompte>]]" +#: diff.c msgid "generate diffstat" msgstr "genera diffstat" +#: diff.c msgid "<width>" msgstr "<amplada>" +#: diff.c msgid "generate diffstat with a given width" msgstr "genera diffstat amb una amplada donada" +#: diff.c msgid "generate diffstat with a given name width" msgstr "genera diffstat amb un nom d'amplada donat" +#: diff.c msgid "generate diffstat with a given graph width" msgstr "genera diffstat amb una amplada de graf donada" +#: diff.c msgid "<count>" msgstr "<comptador>" +#: diff.c msgid "generate diffstat with limited lines" msgstr "genera diffstat amb lÃnies limitades" +#: diff.c msgid "generate compact summary in diffstat" msgstr "genera un resum compacte a diffstat" +#: diff.c msgid "output a binary diff that can be applied" msgstr "diff amb sortida binà ria que pot ser aplicada" +#: diff.c msgid "show full pre- and post-image object names on the \"index\" lines" msgstr "" "mostra els noms complets dels objectes pre i post-imatge a les lÃnies «index»" +#: diff.c msgid "show colored diff" msgstr "mostra un diff amb colors" +#: diff.c msgid "<kind>" msgstr "<kind>" +#: diff.c msgid "" "highlight whitespace errors in the 'context', 'old' or 'new' lines in the " "diff" @@ -16127,6 +20548,7 @@ msgstr "" "ressalta els errors d'espai en blanc a les lÃnies «context», «old» o «new» " "al diff" +#: diff.c msgid "" "do not munge pathnames and use NULs as output field terminators in --raw or " "--numstat" @@ -16134,74 +20556,96 @@ msgstr "" "no consolidis els noms de camà i utilitza NULs com a terminadors de camp de " "sortida en --raw o --numstat" +#: diff.c msgid "<prefix>" msgstr "<prefix>" +#: diff.c msgid "show the given source prefix instead of \"a/\"" msgstr "mostra el prefix d'origen donat en lloc de «a/»" +#: diff.c msgid "show the given destination prefix instead of \"b/\"" msgstr "mostra el prefix de destinació indicat en lloc de «b/»" +#: diff.c msgid "prepend an additional prefix to every line of output" msgstr "afegir un prefix addicional per a cada lÃnia de sortida" +#: diff.c msgid "do not show any source or destination prefix" msgstr "no mostris cap prefix d'origen o destÃ" +#: diff.c msgid "use default prefixes a/ and b/" msgstr "utilitza els prefixos per defecte a/ i b/" +#: diff.c msgid "show context between diff hunks up to the specified number of lines" msgstr "" "mostra el context entre trossos de diferència fins al nombre especificat de " "lÃnies" +#: diff.c msgid "<char>" -msgstr "<char>" +msgstr "<carà cter>" +#: diff.c msgid "specify the character to indicate a new line instead of '+'" msgstr "" "especifiqueu el carà cter per a indicar una lÃnia nova en comptes de «+»" +#: diff.c msgid "specify the character to indicate an old line instead of '-'" msgstr "" "especifiqueu el carà cter per a indicar una lÃnia antiga en comptes de «-»" +#: diff.c msgid "specify the character to indicate a context instead of ' '" msgstr "especifiqueu el carà cter per a indicar context en comptes de « »" +#: diff.c msgid "Diff rename options" msgstr "Opcions de canvi de nom del diff" +#: diff.c msgid "<n>[/<m>]" msgstr "<n>[/<m>]" +#: diff.c msgid "break complete rewrite changes into pairs of delete and create" msgstr "" "divideix els canvis de reescriptura completa en parells de suprimir i crear" +#: diff.c msgid "detect renames" msgstr "detecta els canvis de noms" +#: diff.c msgid "omit the preimage for deletes" msgstr "omet les preimatges per les supressions" +#: diff.c msgid "detect copies" msgstr "detecta còpies" +#: diff.c msgid "use unmodified files as source to find copies" msgstr "usa els fitxers no modificats com a font per a trobar còpies" +#: diff.c msgid "disable rename detection" msgstr "inhabilita la detecció de canvis de nom" +#: diff.c msgid "use empty blobs as rename source" msgstr "usa els blobs buits com a font de canvi de nom" +#: diff.c msgid "continue listing the history of a file beyond renames" msgstr "continua llistant l'històric d'un fitxer més enllà dels canvis de nom" +#: diff.c msgid "" "prevent rename/copy detection if the number of rename/copy targets exceeds " "given limit" @@ -16209,118 +20653,154 @@ msgstr "" "evita la detecció de canvi de nom/còpia si el nombre d'objectius de canvi de " "nom/còpia supera el lÃmit indicat" +#: diff.c msgid "Diff algorithm options" msgstr "Opcions de l'algorisme Diff" +#: diff.c msgid "produce the smallest possible diff" msgstr "produeix el diff més petit possible" +#: diff.c msgid "ignore whitespace when comparing lines" msgstr "ignora els espais en blanc en comparar lÃnies" +#: diff.c msgid "ignore changes in amount of whitespace" msgstr "ignora els canvis en la quantitat d'espai en blanc" +#: diff.c msgid "ignore changes in whitespace at EOL" msgstr "ignora els canvis d'espai en blanc al final de la lÃnia" +#: diff.c msgid "ignore carrier-return at the end of line" msgstr "ignora els retorns de lÃnia al final de la lÃnia" +#: diff.c msgid "ignore changes whose lines are all blank" msgstr "ignora els canvis en lÃnies que estan en blanc" +#: diff.c msgid "<regex>" -msgstr "<regex>" +msgstr "<expr-reg>" +#: diff.c msgid "ignore changes whose all lines match <regex>" -msgstr "ignora els canvis en les lÃnies que coincideixen amb <regex>" +msgstr "ignora els canvis en les lÃnies que coincideixen amb <expr-reg>" +#: diff.c msgid "heuristic to shift diff hunk boundaries for easy reading" msgstr "" "heurÃstica per a desplaçar els lÃmits del tros de diferència per a una " "lectura fà cil" +#: diff.c msgid "generate diff using the \"patience diff\" algorithm" msgstr "genera diff usant l'algorisme «patience diff»" +#: diff.c msgid "generate diff using the \"histogram diff\" algorithm" msgstr "genera diff usant l'algorisme «histogram diff»" +#: diff.c msgid "<text>" msgstr "<text>" +#: diff.c msgid "generate diff using the \"anchored diff\" algorithm" msgstr "genera diff usant l'algorisme «anchored diff»" +#: diff.c msgid "<mode>" msgstr "<mode>" +#: diff.c msgid "show word diff, using <mode> to delimit changed words" msgstr "" "mostra el diff de paraules usant <mode> per a delimitar les paraules " "modificades" +#: diff.c msgid "use <regex> to decide what a word is" -msgstr "utilitza <regex> per a decidir què és una paraula" +msgstr "utilitza <expr-reg> per a decidir què és una paraula" +#: diff.c msgid "equivalent to --word-diff=color --word-diff-regex=<regex>" -msgstr "equivalent a --word-diff=color --word-diff-regex=<regex>" +msgstr "equivalent a --word-diff=color --word-diff-regex=<expr-reg>" +#: diff.c msgid "moved lines of code are colored differently" msgstr "les lÃnies de codi que s'han mogut s'acoloreixen diferent" +#: diff.c msgid "how white spaces are ignored in --color-moved" msgstr "com s'ignoren els espais en blanc a --color-moved" +#: diff.c msgid "Other diff options" msgstr "Altres opcions diff" +#: diff.c msgid "when run from subdir, exclude changes outside and show relative paths" msgstr "" "quan s'executa des d'un subdirectori, exclou els canvis de fora i mostra els " "camins relatius" +#: diff.c msgid "treat all files as text" msgstr "tracta tots els fitxers com a text" +#: diff.c msgid "swap two inputs, reverse the diff" msgstr "intercanvia les dues entrades, inverteix el diff" +#: diff.c msgid "exit with 1 if there were differences, 0 otherwise" msgstr "surt amb 1 si hi ha diferències, 0 en cas contrari" +#: diff.c msgid "disable all output of the program" msgstr "inhabilita totes les sortides del programa" +#: diff.c msgid "allow an external diff helper to be executed" msgstr "permet executar un ajudant de diff extern" +#: diff.c msgid "run external text conversion filters when comparing binary files" msgstr "" "executa els filtres externs de conversió de text en comparar fitxers binaris" +#: diff.c msgid "<when>" msgstr "<quan>" +#: diff.c msgid "ignore changes to submodules in the diff generation" msgstr "ignora els canvis als submòduls en la generació del diff" +#: diff.c msgid "<format>" msgstr "<format>" +#: diff.c msgid "specify how differences in submodules are shown" msgstr "especifiqueu com es mostren els canvis als submòduls" +#: diff.c msgid "hide 'git add -N' entries from the index" msgstr "amaga les entrades «git add -N» de l'Ãndex" +#: diff.c msgid "treat 'git add -N' entries as real in the index" msgstr "tracta les entrades «git add -N» com a reals a l'Ãndex" +#: diff.c msgid "<string>" msgstr "<cadena>" +#: diff.c msgid "" "look for differences that change the number of occurrences of the specified " "string" @@ -16328,6 +20808,7 @@ msgstr "" "cerca les diferències que canvien el nombre d'ocurrències de la cadena " "especificada" +#: diff.c msgid "" "look for differences that change the number of occurrences of the specified " "regex" @@ -16335,27 +20816,35 @@ msgstr "" "cerca les diferències que canvien el nombre d'ocurrències de l'expressió " "regular especificada" +#: diff.c msgid "show all changes in the changeset with -S or -G" msgstr "mostra tots els canvis amb el conjunt de canvis amb -S o -G" +#: diff.c msgid "treat <string> in -S as extended POSIX regular expression" msgstr "tracta <cadena> a -S com a expressió regular POSIX ampliada" +#: diff.c msgid "control the order in which files appear in the output" msgstr "controla l'ordre amb el qual els fitxers apareixen en la sortida" +#: diff.c msgid "<path>" msgstr "<camÃ>" +#: diff.c msgid "show the change in the specified path first" msgstr "mostra el canvi primer al camà especificat" +#: diff.c msgid "skip the output to the specified path" msgstr "omet la sortida al camà especificat" +#: diff.c msgid "<object-id>" msgstr "<id de l'objecte>" +#: diff.c msgid "" "look for differences that change the number of occurrences of the specified " "object" @@ -16363,26 +20852,33 @@ msgstr "" "cerca les diferències que canvien el nombre d'ocurrències de l'objecte " "especificat" +#: diff.c msgid "[(A|C|D|M|R|T|U|X|B)...[*]]" msgstr "[(A|C|D|M|R|T|U|X|B)...[*]]" +#: diff.c msgid "select files by diff type" msgstr "seleccioneu els fitxers per tipus de diff" +#: diff.c msgid "<file>" msgstr "<fitxer>" +#: diff.c msgid "output to a specific file" msgstr "sortida a un fitxer especÃfic" +#: diff.c msgid "exhaustive rename detection was skipped due to too many files." msgstr "" "s'ha omès la detecció de canvi de nom exhaustiva perquè hi ha massa fitxers." +#: diff.c msgid "only found copies from modified paths due to too many files." msgstr "" "només s'han trobat còpies des de camins modificats perquè de massa fitxers." +#: diff.c #, c-format msgid "" "you may want to set your %s variable to at least %d and retry the command." @@ -16390,50 +20886,62 @@ msgstr "" "potser voleu establir la vostra variable %s a almenys %d i tornar a intentar " "l'ordre." +#: diffcore-order.c #, c-format msgid "failed to read orderfile '%s'" msgstr "s'ha produït un error en llegir el fitxer d'ordres «%s»" +#: diffcore-rename.c msgid "Performing inexact rename detection" msgstr "S'està realitzant una detecció inexacta de canvis de nom" +#: diffcore-rotate.c #, c-format msgid "No such path '%s' in the diff" msgstr "No existeix el camà «%s» al diff" +#: dir.c #, c-format msgid "pathspec '%s' did not match any file(s) known to git" msgstr "" "l'especificació de camà «%s» no ha coincidit amb cap fitxer que git conegui" +#: dir.c #, c-format msgid "unrecognized pattern: '%s'" msgstr "patró no reconegut: «%s»" +#: dir.c #, c-format msgid "unrecognized negative pattern: '%s'" msgstr "patró negatiu no reconegut: «%s»" +#: dir.c #, c-format msgid "your sparse-checkout file may have issues: pattern '%s' is repeated" msgstr "" "el vostre fitxer «sparse-checkout» pot tenir problemes el patró «%s» es " "repeteix" +#: dir.c msgid "disabling cone pattern matching" msgstr "inhabilita la coincidència de patrons «cone»" +#: dir.c #, c-format msgid "cannot use %s as an exclude file" msgstr "no es pot usar %s com a fitxer d'exclusió" +#: dir.c msgid "failed to get kernel name and information" msgstr "s'ha produït un error en obtenir el nombre i la informació del nucli" +#: dir.c msgid "untracked cache is disabled on this system or location" msgstr "" "la memòria cau no seguida està inhabilitada en aquest sistema o ubicació" +#: dir.c msgid "" "No directory name could be guessed.\n" "Please specify a directory on the command line" @@ -16441,191 +20949,243 @@ msgstr "" "No s'ha pogut deduir cap nom de directori.\n" "Especifiqueu un directori en la lÃnia d'ordres" +#: dir.c #, c-format msgid "index file corrupt in repo %s" msgstr "el fitxer d'Ãndex al repositori %s és malmès" +#: dir.c #, c-format msgid "could not create directories for %s" msgstr "no s'han pogut crear directoris per %s" +#: dir.c #, c-format msgid "could not migrate git directory from '%s' to '%s'" msgstr "no s'ha pogut migrar el directori de «%s» a «%s»" +#: editor.c #, c-format msgid "hint: Waiting for your editor to close the file...%c" msgstr "consell: s'està esperant que el vostre editor tanqui el fitxer...%c" +#: editor.c sequencer.c wrapper.c #, c-format msgid "could not write to '%s'" msgstr "no s'ha pogut escriure a «%s»" +#: editor.c #, c-format msgid "could not edit '%s'" msgstr "no s'ha pogut editar «%s»" +#: entry.c msgid "Filtering content" msgstr "S'està filtrant el contingut" +#: entry.c #, c-format msgid "could not stat file '%s'" msgstr "no s'ha pogut fer «stat» sobre el fitxer «%s»" +#: environment.c #, c-format msgid "bad git namespace path \"%s\"" msgstr "camà d'espai de noms git incorrecte «%s»" +#: exec-cmd.c #, c-format msgid "too many args to run %s" msgstr "hi ha massa arguments per a executar %s" +#: fetch-pack.c msgid "git fetch-pack: expected shallow list" msgstr "git fetch-pack: llista shallow esperada" +#: fetch-pack.c msgid "git fetch-pack: expected a flush packet after shallow list" msgstr "" "git fetch-pack: s'esperava un paquet de buidatge després d'una llista shallow" +#: fetch-pack.c msgid "git fetch-pack: expected ACK/NAK, got a flush packet" msgstr "git fetch-pack: s'esperava ACK/NAK, s'ha rebut un paquet de buidatge" +#: fetch-pack.c #, c-format msgid "git fetch-pack: expected ACK/NAK, got '%s'" msgstr "git fetch-pack: s'esperava ACK/NAK, s'ha rebut «%s»" +#: fetch-pack.c msgid "unable to write to remote" msgstr "no s'ha pogut escriure al remot" +#: fetch-pack.c msgid "Server supports filter" msgstr "El servidor accepta filtratge" +#: fetch-pack.c #, c-format msgid "invalid shallow line: %s" msgstr "lÃnia de shallow no và lida: %s" +#: fetch-pack.c #, c-format msgid "invalid unshallow line: %s" msgstr "lÃnia d'unshallow no và lida: %s" +#: fetch-pack.c #, c-format msgid "object not found: %s" msgstr "objecte no trobat: %s" +#: fetch-pack.c #, c-format msgid "error in object: %s" msgstr "error en objecte: %s" +#: fetch-pack.c #, c-format msgid "no shallow found: %s" msgstr "no s'ha trobat cap shallow: %s" +#: fetch-pack.c #, c-format msgid "expected shallow/unshallow, got %s" msgstr "s'esperava shallow/unshallow, s'ha rebut %s" +#: fetch-pack.c #, c-format msgid "got %s %d %s" msgstr "s'ha rebut %s %d %s" +#: fetch-pack.c #, c-format msgid "invalid commit %s" msgstr "comissió no và lida %s" +#: fetch-pack.c msgid "giving up" msgstr "s'abandona" +#: fetch-pack.c progress.h msgid "done" msgstr "fet" +#: fetch-pack.c #, c-format msgid "got %s (%d) %s" msgstr "s'ha rebut %s (%d) %s" +#: fetch-pack.c #, c-format msgid "Marking %s as complete" msgstr "S'està marcant %s com a complet" +#: fetch-pack.c #, c-format msgid "already have %s (%s)" msgstr "ja es té %s (%s)" +#: fetch-pack.c msgid "fetch-pack: unable to fork off sideband demultiplexer" msgstr "fetch-pack: no s'ha pogut bifurcar del desmultiplexor de banda lateral" +#: fetch-pack.c msgid "protocol error: bad pack header" msgstr "error de protocol: capçalera de paquet errònia" +#: fetch-pack.c #, c-format msgid "fetch-pack: unable to fork off %s" msgstr "fetch-pack: no es pot bifurcar de %s" +#: fetch-pack.c msgid "fetch-pack: invalid index-pack output" msgstr "fetch-pack: sortida d'index-pack no và lida" +#: fetch-pack.c #, c-format msgid "%s failed" msgstr "%s ha fallat" +#: fetch-pack.c msgid "error in sideband demultiplexer" msgstr "error en desmultiplexor de banda lateral" +#: fetch-pack.c #, c-format msgid "Server version is %.*s" msgstr "La versió del servidor és %.*s" +#: fetch-pack.c #, c-format msgid "Server supports %s" msgstr "El servidor accepta %s" +#: fetch-pack.c msgid "Server does not support shallow clients" msgstr "El servidor no permet clients superficials" +#: fetch-pack.c msgid "Server does not support --shallow-since" msgstr "El servidor no admet --shallow-since" +#: fetch-pack.c msgid "Server does not support --shallow-exclude" msgstr "El servidor no admet --shallow-exclude" +#: fetch-pack.c msgid "Server does not support --deepen" msgstr "El servidor no admet --deepen" +#: fetch-pack.c msgid "Server does not support this repository's object format" msgstr "" "El servidor no és compatible amb el format d'objecte d'aquest repositori" +#: fetch-pack.c msgid "no common commits" msgstr "cap comissió en comú" +#: fetch-pack.c msgid "git fetch-pack: fetch failed." msgstr "git fetch-pack: l'obtenció ha fallat." +#: fetch-pack.c #, c-format msgid "mismatched algorithms: client %s; server %s" msgstr "algoritmes no coincidents: client %s; servidor %s" +#: fetch-pack.c #, c-format msgid "the server does not support algorithm '%s'" msgstr "el servidor no és compatible amb l'algorisme «%s»" +#: fetch-pack.c msgid "Server does not support shallow requests" msgstr "El servidor no permet sol·licituds superficials" +#: fetch-pack.c msgid "unable to write request to remote" msgstr "no s'ha pogut escriure la sol·licitud al remot" +#: fetch-pack.c #, c-format msgid "expected '%s', received '%s'" msgstr "s'esperava «%s», s'ha rebut «%s»" +#: fetch-pack.c #, c-format msgid "expected '%s'" msgstr "s'esperava «%s»" +#: fetch-pack.c #, c-format msgid "unexpected acknowledgment line: '%s'" msgstr "lÃnia de confirmació inesperada: «%s»" +#: fetch-pack.c #, c-format msgid "error processing acks: %d" msgstr "s'ha produït un error en processar els acks: %d" @@ -16633,6 +21193,7 @@ msgstr "s'ha produït un error en processar els acks: %d" #. TRANSLATORS: The parameter will be 'ready', a protocol #. keyword. #. +#: fetch-pack.c #, c-format msgid "expected packfile to be sent after '%s'" msgstr "s'esperava que el fitxer de paquet s'enviés després de «%s»" @@ -16640,74 +21201,93 @@ msgstr "s'esperava que el fitxer de paquet s'enviés després de «%s»" #. TRANSLATORS: The parameter will be 'ready', a protocol #. keyword. #. +#: fetch-pack.c #, c-format msgid "expected no other sections to be sent after no '%s'" msgstr "no s'esperava que cap altra secció s'enviés després de «%s»" +#: fetch-pack.c #, c-format msgid "error processing shallow info: %d" msgstr "s'ha produït un error en processar la informació superficial: %d" +#: fetch-pack.c #, c-format msgid "expected wanted-ref, got '%s'" msgstr "s'esperava wanted-ref, s'ha rebut «%s»" +#: fetch-pack.c #, c-format msgid "unexpected wanted-ref: '%s'" msgstr "wanted-ref inesperat: «%s»" +#: fetch-pack.c #, c-format msgid "error processing wanted refs: %d" msgstr "s'ha produït un error en processar les referències desitjades: %d" +#: fetch-pack.c msgid "git fetch-pack: expected response end packet" msgstr "git fetch-pack: s'esperava un paquet de final de resposta" +#: fetch-pack.c msgid "no matching remote head" msgstr "no hi ha cap HEAD remot coincident" +#: fetch-pack.c msgid "unexpected 'ready' from remote" msgstr "«ready» no esperat des del remot" +#: fetch-pack.c #, c-format msgid "no such remote ref %s" msgstr "no existeix la referència remota %s" +#: fetch-pack.c #, c-format msgid "Server does not allow request for unadvertised object %s" msgstr "El servidor no permet sol·licitar objectes no anunciats %s" +#: fsmonitor-ipc.c #, c-format msgid "fsmonitor_ipc__send_query: invalid path '%s'" msgstr "fsmonitor_ipc__send_query: camà no và lid «%s»" +#: fsmonitor-ipc.c #, c-format msgid "fsmonitor_ipc__send_query: unspecified error on '%s'" msgstr "fsmonitor_ipc__send_query: error no especificat en «%s»" +#: fsmonitor-ipc.c msgid "fsmonitor--daemon is not running" msgstr "fsmonitor--daemon no s'està executant" +#: fsmonitor-ipc.c #, c-format msgid "could not send '%s' command to fsmonitor--daemon" msgstr "no s'ha pogut enviar l'ordre «%s» a fsmonitor--daemon" +#: fsmonitor-settings.c #, c-format msgid "bare repository '%s' is incompatible with fsmonitor" msgstr "el repositori nu «%s» és incompatible amb fsmonitor" +#: fsmonitor-settings.c #, c-format msgid "repository '%s' is incompatible with fsmonitor due to errors" msgstr "el repositori «%s» és incompatible amb fsmonitor a causa d'errors" +#: fsmonitor-settings.c #, c-format msgid "remote repository '%s' is incompatible with fsmonitor" msgstr "el repositori remot «%s» no és compatible amb fsmonitor" +#: fsmonitor-settings.c #, c-format msgid "virtual repository '%s' is incompatible with fsmonitor" msgstr "el repositori virtual «%s» és incompatible amb fsmonitor" +#: fsmonitor-settings.c #, c-format msgid "" "socket directory '%s' is incompatible with fsmonitor due to lack of Unix " @@ -16716,21 +21296,27 @@ msgstr "" "el directori del sòcol «%s» és incompatible amb fsmonitor a causa de la " "manca de compatibilitat amb els sòcols Unix" +#: git.c msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" -msgstr "" -"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" -" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" - +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" +msgstr "" +"git [-v | --version] [-h | --help] [-C <camÃ>] [-c <nom>=<valor>]\n" +" [--exec-path[=<camÃ>]] [--html-path] [--man-path] [--info-path]\n" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<camÃ>]\n" +" [--work-tree=<camÃ>] [--namespace=<nom>] [--config-" +"env=<nom>=<variable-d-entorn>]\n" +" <ordre> [<arguments>]" + +#: git.c msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" "concept guides. See 'git help <command>' or 'git help <concept>'\n" @@ -16742,38 +21328,47 @@ msgstr "" "«git help <concepte>» per a llegir sobre una subordre o concepte\n" "especÃfic. Vegeu «git help git» per a una visió general del sistema." +#: git.c help.c #, c-format msgid "unsupported command listing type '%s'" msgstr "tipus de llistat de l'ordre no compatible «%s»" +#: git.c #, c-format msgid "no directory given for '%s' option\n" msgstr "no s'ha especificat un directori per a l'opció «%s»\n" +#: git.c #, c-format msgid "no namespace given for --namespace\n" msgstr "no s'ha especificat un nom d'espai per --namespace\n" +#: git.c #, c-format msgid "-c expects a configuration string\n" msgstr "-c espera una cadena de configuració\n" +#: git.c #, c-format msgid "no config key given for --config-env\n" msgstr "no s'ha indicat cap clau de configuració per a --config-env\n" +#: git.c #, c-format msgid "no attribute source given for --attr-source\n" msgstr "no s'ha donat d'atribut font per a --attr-source\n" +#: git.c #, c-format msgid "unknown option: %s\n" msgstr "opció desconeguda: %s\n" +#: git.c #, c-format msgid "while expanding alias '%s': '%s'" msgstr "en expandir l'à lies «%s»: «%s»" +#: git.c #, c-format msgid "" "alias '%s' changes environment variables.\n" @@ -16782,31 +21377,39 @@ msgstr "" "l'à lies «%s» canvia variables d'entorn.\n" "Podeu utilitzar «!git» a l'à lies per a fer-ho" +#: git.c #, c-format msgid "empty alias for %s" msgstr "à lies buit per a %s" +#: git.c #, c-format msgid "recursive alias: %s" msgstr "à lies recursiu: %s" +#: git.c msgid "write failure on standard output" msgstr "fallada d'escriptura en la sortida està ndard" +#: git.c msgid "unknown write failure on standard output" msgstr "fallada d'escriptura desconeguda en la sortida està ndard" +#: git.c msgid "close failed on standard output" msgstr "ha fallat el tancament en la sortida està ndard" +#: git.c #, c-format msgid "alias loop detected: expansion of '%s' does not terminate:%s" msgstr "bucle d'à lies detectat expansió de «%s» no acaba:%s" +#: git.c #, c-format msgid "cannot handle %s as a builtin" msgstr "no es pot gestionar %s com a integrat" +#: git.c #, c-format msgid "" "usage: %s\n" @@ -16815,21 +21418,26 @@ msgstr "" "ús: %s\n" "\n" +#: git.c #, c-format msgid "expansion of alias '%s' failed; '%s' is not a git command\n" msgstr "ha fallat l'expansió de l'à lies «%s»; «%s» no és una ordre git\n" +#: git.c #, c-format msgid "failed to run command '%s': %s\n" msgstr "s'ha produït un error en executar l'ordre «%s»: %s\n" +#: gpg-interface.c msgid "could not create temporary file" msgstr "no s'ha pogut crear el fitxer temporal" +#: gpg-interface.c #, c-format msgid "failed writing detached signature to '%s'" msgstr "s'ha produït un error en escriure la clau de signatura separada a «%s»" +#: gpg-interface.c msgid "" "gpg.ssh.allowedSignersFile needs to be configured and exist for ssh " "signature verification" @@ -16837,6 +21445,7 @@ msgstr "" "gpg.ssh.allowedSignersFile s'ha de configurar i existeix per a la " "verificació de la signatura ssh" +#: gpg-interface.c msgid "" "ssh-keygen -Y find-principals/verify is needed for ssh signature " "verification (available in openssh version 8.2p1+)" @@ -16844,32 +21453,39 @@ msgstr "" "ssh-keygen -Y find-principals/verify és necessari per a la verificació de la " "signatura ssh (disponible a opensh versió 8.2p1+)" +#: gpg-interface.c #, c-format msgid "ssh signing revocation file configured but not found: %s" msgstr "fitxer de revocació de la signatura ssh configurat però no trobat: %s" +#: gpg-interface.c #, c-format msgid "bad/incompatible signature '%s'" msgstr "la signatura «%s» és incompatible o està malmesa" +#: gpg-interface.c #, c-format msgid "failed to get the ssh fingerprint for key '%s'" msgstr "no s'ha pogut obtenir l'empremta ssh de la clau «%s»" +#: gpg-interface.c msgid "" "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured" msgstr "" "o bé user.signingkey o gpg.ssh.defaultKeyCommand han de ser configurats" +#: gpg-interface.c #, c-format msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s" msgstr "" "gpg.ssh.defaultKeyCommand ha tingut èxit però no ha retornat cap clau: %s %s" +#: gpg-interface.c #, c-format msgid "gpg.ssh.defaultKeyCommand failed: %s %s" msgstr "gpg.ssh.defaultKeyCommand ha fallat: %s %s" +#: gpg-interface.c #, c-format msgid "" "gpg failed to sign the data:\n" @@ -16878,17 +21494,21 @@ msgstr "" "gpg ha fallat en signar les dades:\n" "%s" +#: gpg-interface.c msgid "user.signingKey needs to be set for ssh signing" msgstr "user.signingKey s'ha d'establir per a signar amb ssh" +#: gpg-interface.c #, c-format msgid "failed writing ssh signing key to '%s'" msgstr "s'ha produït un error en escriure la clau de signatura ssh a «%s»" +#: gpg-interface.c #, c-format msgid "failed writing ssh signing key buffer to '%s'" msgstr "s'ha produït un error en escriure la clau de signatura ssh a «%s»" +#: gpg-interface.c msgid "" "ssh-keygen -Y sign is needed for ssh signing (available in openssh version " "8.2p1+)" @@ -16896,102 +21516,132 @@ msgstr "" "ssh-keygen -Y sign és necessari per a signar amb ssh (disponible a openssh " "versió 8.2p1+)" +#: gpg-interface.c #, c-format msgid "failed reading ssh signing data buffer from '%s'" msgstr "s'ha produït un error en llegir la signatura ssh des de «%s»" +#: graph.c #, c-format msgid "ignored invalid color '%.*s' in log.graphColors" msgstr "ignora el color no và lid «%.*s» a log.graphColors" +#: grep.c msgid "" "given pattern contains NULL byte (via -f <file>). This is only supported " "with -P under PCRE v2" msgstr "" -"el patró indicat conté byte NULL (via -f <fitxer>). Això només és compatible " -"amb -P sota PCRE v2" +"el patró indicat conté l'octet NULL (via -f <fitxer>). Això només és " +"compatible amb -P sota PCRE v2" +#: grep.c #, c-format msgid "'%s': unable to read %s" msgstr "«%s»: no s'ha pogut llegir %s" +#: grep.c #, c-format msgid "'%s': short read" msgstr "«%s»: lectura curta" +#: help.c msgid "start a working area (see also: git help tutorial)" msgstr "començar una à rea de treball (vegeu també: git help tutorial)" +#: help.c msgid "work on the current change (see also: git help everyday)" msgstr "treballar en el canvi actual (vegeu també: git help everyday)" +#: help.c msgid "examine the history and state (see also: git help revisions)" msgstr "examinar la història i l'estat (vegeu també: git help revisions)" +#: help.c msgid "grow, mark and tweak your common history" msgstr "fer créixer, marcar i ajustar la vostra història comuna" +#: help.c msgid "collaborate (see also: git help workflows)" msgstr "col·laborar (vegeu també: git help workflow)" +#: help.c msgid "Main Porcelain Commands" msgstr "Ordres principals de porcellana" +#: help.c msgid "Ancillary Commands / Manipulators" msgstr "Ordres auxiliars / manipuladors" +#: help.c msgid "Ancillary Commands / Interrogators" msgstr "Ordres auxiliars / interrogadors" +#: help.c msgid "Interacting with Others" msgstr "Interaccionar amb altres" +#: help.c msgid "Low-level Commands / Manipulators" msgstr "Ordres de baix nivell / Manipuladors" +#: help.c msgid "Low-level Commands / Interrogators" msgstr "Ordres de baix nivell / Interrogadors" +#: help.c msgid "Low-level Commands / Syncing Repositories" msgstr "Ordres de baix nivell / Sincronització de repositoris" +#: help.c msgid "Low-level Commands / Internal Helpers" msgstr "Ordres de baix nivell / Ajudants interns" +#: help.c msgid "User-facing repository, command and file interfaces" msgstr "Repositori, ordre i interfÃcie de fitxers que veu l'usuari" +#: help.c msgid "Developer-facing file formats, protocols and other interfaces" -msgstr "Formats de fitxers, protocols i interfÃcies que veu el desenvolupador" +msgstr "Formats de fitxer, protocols i interfÃcies que veu el desenvolupador" +#: help.c #, c-format msgid "available git commands in '%s'" msgstr "ordres de git disponibles en «%s»" +#: help.c msgid "git commands available from elsewhere on your $PATH" msgstr "ordres de git disponibles d'altres llocs en el vostre $PATH" +#: help.c msgid "These are common Git commands used in various situations:" msgstr "Aquestes són ordres habituals del Git usades en diverses situacions:" +#: help.c msgid "The Git concept guides are:" msgstr "Les guies de Git de conceptes són:" +#: help.c msgid "User-facing repository, command and file interfaces:" msgstr "Repositori, ordre i interfÃcie de fitxers que veu l'usuari:" +#: help.c msgid "File formats, protocols and other developer interfaces:" msgstr "Formats de fitxer, protocols i altres interfÃcies de desenvolupador:" +#: help.c msgid "External commands" msgstr "Ordres externes" +#: help.c msgid "Command aliases" msgstr "Àlies d'ordres" +#: help.c msgid "See 'git help <command>' to read about a specific subcommand" msgstr "Vegeu «git help <ordre>» per a llegir sobre una subordre especÃfica" +#: help.c #, c-format msgid "" "'%s' appears to be a git command, but we were not\n" @@ -17000,31 +21650,38 @@ msgstr "" "«%s» sembla una ordre de git, però no hem pogut\n" "executar-la. Pot ser que git-%s estigui malmès?" +#: help.c #, c-format msgid "git: '%s' is not a git command. See 'git --help'." msgstr "git: «%s» no és una ordre de git. Vegeu «git --help»." +#: help.c msgid "Uh oh. Your system reports no Git commands at all." msgstr "Ai. El vostre sistema no informa de cap ordre de Git." +#: help.c #, c-format msgid "WARNING: You called a Git command named '%s', which does not exist." msgstr "" "ADVERTÈNCIA: Heu invocat una ordre de Git amb nom «%s», la qual no existeix." +#: help.c #, c-format msgid "Continuing under the assumption that you meant '%s'." msgstr "El procés continuarà , pressuposant que volÃeu dir «%s»." +#: help.c #, c-format msgid "Run '%s' instead [y/N]? " msgstr "Voleu executar «%s» en el seu lloc? [y/N]? " +#: help.c #, c-format msgid "Continuing in %0.1f seconds, assuming that you meant '%s'." msgstr "" "El procés continuarà en %0.1f segons, pressuposant que volÃeu dir «%s»." +#: help.c msgid "" "\n" "The most similar command is" @@ -17038,13 +21695,16 @@ msgstr[1] "" "\n" "Les ordres més similars són" +#: help.c msgid "git version [--build-options]" msgstr "git version [--build-options]" +#: help.c #, c-format msgid "%s: %s - %s" msgstr "%s: %s - %s" +#: help.c msgid "" "\n" "Did you mean this?" @@ -17058,6 +21718,7 @@ msgstr[1] "" "\n" "VolÃeu dir un d'aquests?" +#: hook.c #, c-format msgid "" "The '%s' hook was ignored because it's not set as executable.\n" @@ -17066,40 +21727,62 @@ msgstr "" "El lligam «%s» s'ha ignorat perquè no s'ha establert com a executable.\n" "Podeu desactivar aquest avÃs amb «git config advice.ignoredHook false»." +#: http-fetch.c +msgid "not a git repository" +msgstr "no és un repositori de git" + +#: http-fetch.c #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "l'argument a --packfile ha de ser un resum và lid (s'ha obtingut «%s»)" -msgid "not a git repository" -msgstr "no és un repositori de git" - +#: http.c #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "valor negatiu per http.postBuffer; utilitzant el valor %d" +#: http.c msgid "Delegation control is not supported with cURL < 7.22.0" msgstr "No s'admet el control de delegació amb el cURL < 7.22.0" +#: http.c msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "No s'admet la fixació de clau pública amb cURL < 7.39.0" +#: http.c +msgid "Unknown value for http.proactiveauth" +msgstr "Valor desconegut de http.proactiveauth" + +#: http.c msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE no està admès amb cURL < 7.44.0" +#: http.c #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "El rerefons SSL «%s» no està admès. Els rerefons SSL admesos:" +#: http.c #, c-format msgid "Could not set SSL backend to '%s': cURL was built without SSL backends" msgstr "" "No s'ha pogut establir el rerefons SSL a «%s»: cURL es va construir sense " "rerefons SSL" +#: http.c #, c-format msgid "Could not set SSL backend to '%s': already set" msgstr "No s'ha pogut establir el rerefons SSL a «%s»: ja establert" +#: http.c +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "res'ha rebutjat llegir galetes del http.cookiefile «-»" + +#: http.c +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "s'està ignorant http.savecookies per al http.cookiefile buit" + +#: http.c #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17110,12 +21793,15 @@ msgstr "" " petició: %s\n" " redirecció: %s" +#: ident.c msgid "Author identity unknown\n" msgstr "Identitat de l'autor desconeguda\n" +#: ident.c msgid "Committer identity unknown\n" msgstr "Es desconeix la identitat del comitent\n" +#: ident.c msgid "" "\n" "*** Please tell me who you are.\n" @@ -17140,88 +21826,110 @@ msgstr "" "per a establir la identitat predeterminada del vostre compte.\n" "Ometeu --global per a establir la identitat només en aquest repositori.\n" +#: ident.c msgid "no email was given and auto-detection is disabled" msgstr "" "no s'ha proporcionat cap adreça electrònica i la detecció automà tica està " "inhabilitada" +#: ident.c #, c-format msgid "unable to auto-detect email address (got '%s')" msgstr "" "no s'ha pogut detectar automà ticament una adreça electrònica và lida (s'ha " "rebut «%s»)" +#: ident.c msgid "no name was given and auto-detection is disabled" msgstr "" "no s'ha proporcionat cap nom i la detecció automà tica està inhabilitada" +#: ident.c #, c-format msgid "unable to auto-detect name (got '%s')" msgstr "no s'ha pogut detectar automà ticament el nom (s'ha rebut «%s»)" +#: ident.c #, c-format msgid "empty ident name (for <%s>) not allowed" msgstr "nom d'identitat buit (per <%s>) no és permès" +#: ident.c #, c-format msgid "name consists only of disallowed characters: %s" msgstr "el nom conté només carà cters no permesos: %s" +#: list-objects-filter-options.c msgid "expected 'tree:<depth>'" msgstr "s'esperava «tree:<profunditat>»" +#: list-objects-filter-options.c msgid "sparse:path filters support has been dropped" msgstr "sparse: s'ha eliminat la implementació de filtres de camà sparse" +#: list-objects-filter-options.c #, c-format msgid "'%s' for 'object:type=<type>' is not a valid object type" msgstr "«%s» per a «object:type=<tipus>» no és un tipus d'objecte và lid" +#: list-objects-filter-options.c #, c-format msgid "invalid filter-spec '%s'" msgstr "filtre d'especificació no và lid: «%s»" +#: list-objects-filter-options.c #, c-format msgid "must escape char in sub-filter-spec: '%c'" msgstr "cal escapar el carà cter en el sub-filter-spec «%c»" +#: list-objects-filter-options.c msgid "expected something after combine:" msgstr "s'esperava alguna cosa després de combinar:" +#: list-objects-filter-options.c msgid "multiple filter-specs cannot be combined" msgstr "no es poden combinar múltiples especificacions de filtratge" +#: list-objects-filter-options.c msgid "unable to upgrade repository format to support partial clone" msgstr "" "no s'ha pogut actualitzar el format del repositori perquè sigui compatible " "amb un clonatge parcial" +#: list-objects-filter-options.h msgid "args" msgstr "arguments" +#: list-objects-filter-options.h msgid "object filtering" msgstr "filtratge d'objecte" +#: list-objects-filter.c #, c-format msgid "unable to access sparse blob in '%s'" msgstr "no s'ha pogut accedir a un blob dispers en «%s»" +#: list-objects-filter.c #, c-format msgid "unable to parse sparse filter data in %s" msgstr "no s'han pogut analitzar les dades disperses filtrades %s" +#: list-objects.c #, c-format msgid "entry '%s' in tree %s has tree mode, but is not a tree" msgstr "l'entrada «%s» a l'arbre %s té mode d'arbre, però no és un arbre" +#: list-objects.c #, c-format msgid "entry '%s' in tree %s has blob mode, but is not a blob" msgstr "l'entrada «%s» a l'arbre %s té mode blob, però no és un blob" +#: list-objects.c #, c-format msgid "unable to load root tree for commit %s" msgstr "no s'ha pogut carregar l'arrel de l'arbre per la comissió %s" +#: lockfile.c #, c-format msgid "" "Unable to create '%s.lock': %s.\n" @@ -17241,46 +21949,82 @@ msgstr "" "ha fallat en aquest repositori abans:\n" "elimineu el fitxer manualment per a continuar." +#: lockfile.c #, c-format msgid "Unable to create '%s.lock': %s" msgstr "No s'ha pogut crear «%s.lock»: %s" +#: log-tree.c +msgid "unable to create temporary object directory" +msgstr "no s'ha pogut crear el directori temporal de l'objecte" + +#: loose.c +#, c-format +msgid "could not write loose object index %s" +msgstr "no s'ha pogut escriure l'Ãndex d'objecte solt %s" + +#: loose.c +#, c-format +msgid "failed to write loose object index %s" +msgstr "no s'ha pogut escriure l'Ãndex d'objectes solts %s" + +#: ls-refs.c #, c-format msgid "unexpected line: '%s'" msgstr "lÃnia inesperada: «%s»" +#: ls-refs.c msgid "expected flush after ls-refs arguments" msgstr "s'esperava una neteja després dels arguments ls-refs" +#: mailinfo.c msgid "quoted CRLF detected" msgstr "CRLF entre cometes detectat" +#: mem-pool.c strbuf.c wrapper.c +#, c-format +msgid "unable to format message: %s" +msgstr "no es pot formatar el missatge: %s" + +#: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "S'ha produït un error en fusionar el submòdul %s (no està agafat)" +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (no merge base)" msgstr "S'ha produït un error en fusionar el submòdul %s (no hi ha fusió base)" +#: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (commits not present)" msgstr "S'ha produït un error en fusionar el submòdul %s (no hi ha comissions)" +# corrupt → malmès OK per a repositori? +#: merge-ort.c +#, c-format +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "error: no s'ha pogut fusionar el submòdul %s (repositori malmès)" + +#: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" "S'ha produït un error en fusionar el submòdul %s (les comissions no " "segueixen merge-base)" +#: merge-ort.c #, c-format msgid "Note: Fast-forwarding submodule %s to %s" msgstr "Nota: avançament rà pid del submòdul %s a %s" +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s" msgstr "S'ha produït un error en fusionar el submòdul «%s»" +#: merge-ort.c #, c-format msgid "" "Failed to merge submodule %s, but a possible merge resolution exists: %s" @@ -17288,6 +22032,7 @@ msgstr "" "S'ha produït un error en fusionar el submòdul %s, però existeix una solució " "possible: %s" +#: merge-ort.c #, c-format msgid "" "Failed to merge submodule %s, but multiple possible merges exist:\n" @@ -17297,17 +22042,22 @@ msgstr "" "solucions possibles:\n" "%s" -msgid "failed to execute internal merge" -msgstr "no s'ha pogut executar la fusió interna" +#: merge-ort.c +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "no s'ha pogut executar la fusió interna per a %s" +#: merge-ort.c #, c-format -msgid "unable to add %s to database" -msgstr "no s'ha pogut afegir %s a la base de dades" +msgid "error: unable to add %s to database" +msgstr "error: no es pot afegir %s a la base de dades" +#: merge-ort.c merge-recursive.c #, c-format msgid "Auto-merging %s" msgstr "S'està autofusionant %s" +#: merge-ort.c merge-recursive.c #, c-format msgid "" "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of " @@ -17317,6 +22067,7 @@ msgstr "" "existent a %s en forma de canvi del nom del directori implÃcit, posant-hi " "els camins següents a: %s." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "CONFLICT (implicit dir rename): Cannot map more than one path to %s; " @@ -17326,6 +22077,7 @@ msgstr "" "camà a %s; els canvis del nom del directori implÃcits han intentat posar " "aquests camins a: %s segons" +#: merge-ort.c #, c-format msgid "" "CONFLICT (directory rename split): Unclear where to rename %s to; it was " @@ -17336,6 +22088,7 @@ msgstr "" "%s; s'han canviat de nom a múltiples altres directoris, sense una destinació " "per a la majoria dels fitxers." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " @@ -17344,6 +22097,7 @@ msgstr "" "AVÃS: S'està evitant aplicar el canvi de nom %s -> %s a %s, perquè %s ell " "mateix ja havia canviat de nom." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "Path updated: %s added in %s inside a directory that was renamed in %s; " @@ -17352,6 +22106,7 @@ msgstr "" "Pedaç actualitzat: %s afegit a %s dins d'un directori que va canviar de nom " "a %s; movent-lo a %s." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "Path updated: %s renamed to %s in %s, inside a directory that was renamed in " @@ -17360,6 +22115,7 @@ msgstr "" "Pedaç actualitzat: %s canviat al nom %s a %s, dins d'un directori que va " "canviar de nom a %s; movent-lo a %s." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "CONFLICT (file location): %s added in %s inside a directory that was renamed " @@ -17368,6 +22124,7 @@ msgstr "" "CONFLICTE (ubicació del fitxer): %s afegit a %s dins d'un directori que va " "canviar de nom a %s suggerint que potser hauria de moure's a %s." +#: merge-ort.c merge-recursive.c #, c-format msgid "" "CONFLICT (file location): %s renamed to %s in %s, inside a directory that " @@ -17377,11 +22134,13 @@ msgstr "" "directori que va canviar de nom a %s, suggerint que potser hauria de moure's " "a %s." +#: merge-ort.c #, c-format msgid "CONFLICT (rename/rename): %s renamed to %s in %s and to %s in %s." msgstr "" "CONFLICTE (canvi de nom/canvi de nom): %s ara té el nom %s a %s i %s a %s." +#: merge-ort.c #, c-format msgid "" "CONFLICT (rename involved in collision): rename of %s -> %s has content " @@ -17392,20 +22151,24 @@ msgstr "" "%s té conflictes de contingut i col·lisiona amb un altre camÃ; això pot " "donar lloc a marcadors de conflicte imbricats." +#: merge-ort.c #, c-format msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s." msgstr "" "CONFLICTE (canvi de nom/supressió): %s ara té el nom %s a %s, però s'ha " "suprimit a %s." +#: merge-ort.c #, c-format -msgid "cannot read object %s" -msgstr "no es pot llegir l'objecte %s" +msgid "error: cannot read object %s" +msgstr "error: no es pot llegir l'objecte %s" +#: merge-ort.c #, c-format -msgid "object %s is not a blob" -msgstr "l'objecte %s no és un blob" +msgid "error: object %s is not a blob" +msgstr "error: l'objecte %s no és un blob" +#: merge-ort.c #, c-format msgid "" "CONFLICT (file/directory): directory in the way of %s from %s; moving it to " @@ -17414,6 +22177,7 @@ msgstr "" "CONFLICTE (fitxer/directori): directori en el camà de %s des de %s; en " "comptes es mou a %s." +#: merge-ort.c #, c-format msgid "" "CONFLICT (distinct types): %s had different types on each side; renamed both " @@ -17422,6 +22186,7 @@ msgstr "" "CONFLICTE (tipus diferents): %s tenia diferents tipus a cada costat; se'ls " "ha canviat el nom per tal que cadascun pugui ser registrat en algun lloc." +#: merge-ort.c #, c-format msgid "" "CONFLICT (distinct types): %s had different types on each side; renamed one " @@ -17431,19 +22196,24 @@ msgstr "" "canviat el nom d'un d'ells per tal que cadascun pugui ser registrat en algun " "lloc." +#: merge-ort.c merge-recursive.c msgid "content" msgstr "contingut" +#: merge-ort.c merge-recursive.c msgid "add/add" msgstr "afegiment/afegiment" +#: merge-ort.c merge-recursive.c msgid "submodule" msgstr "submòdul" +#: merge-ort.c merge-recursive.c #, c-format msgid "CONFLICT (%s): Merge conflict in %s" msgstr "CONFLICTE (%s): Conflicte de fusió en %s" +#: merge-ort.c #, c-format msgid "" "CONFLICT (modify/delete): %s deleted in %s and modified in %s. Version %s " @@ -17458,6 +22228,7 @@ msgstr "" #. commit that needs to be merged. For example: #. - go to submodule (mysubmodule), and either merge commit abc1234" #. +#: merge-ort.c #, c-format msgid "" " - go to submodule (%s), and either merge commit %s\n" @@ -17466,6 +22237,7 @@ msgstr "" " - aneu al submòdul (%s), i fusioneu la comissió %s\n" " o actualitzeu-la a una comissió existent que ha fusionat aquests canvis\n" +#: merge-ort.c #, c-format msgid "" "Recursive merging with submodules currently only supports trivial cases.\n" @@ -17493,75 +22265,98 @@ msgstr "" #. TRANSLATORS: The %s arguments are: 1) tree hash of a merge #. base, and 2-3) the trees for the two trees we're merging. #. +#: merge-ort.c #, c-format msgid "collecting merge info failed for trees %s, %s, %s" msgstr "" "ha fallat la recollida de la informació de fusió per als arbres %s, %s, %s" +#: merge-recursive.c msgid "(bad commit)\n" msgstr "(comissió errònia)\n" +#: merge-recursive.c #, c-format msgid "add_cacheinfo failed for path '%s'; merge aborting." msgstr "add_cacheinfo ha fallat per al camà «%s»; interrompent la fusió." +#: merge-recursive.c #, c-format msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." msgstr "" "add_cacheinfo ha fallat al refrescar el camà «%s»; interrompent la fusió." +#: merge-recursive.c #, c-format msgid "failed to create path '%s'%s" msgstr "s'ha produït un error en crear el camà «%s»%s" +#: merge-recursive.c #, c-format msgid "Removing %s to make room for subdirectory\n" msgstr "S'està eliminant %s per a fer espai per al subdirectori\n" +#: merge-recursive.c msgid ": perhaps a D/F conflict?" msgstr ": potser un conflicte D/F?" +#: merge-recursive.c #, c-format msgid "refusing to lose untracked file at '%s'" msgstr "s'està refusant perdre el fitxer no seguit a «%s»" +#: merge-recursive.c #, c-format msgid "blob expected for %s '%s'" msgstr "blob esperat per a %s «%s»" +#: merge-recursive.c #, c-format msgid "failed to open '%s': %s" msgstr "s'ha produït un error en obrir «%s»: %s" +#: merge-recursive.c #, c-format msgid "failed to symlink '%s': %s" msgstr "s'ha produït un error en fer l'enllaç simbòlic «%s»: %s" +#: merge-recursive.c #, c-format msgid "do not know what to do with %06o %s '%s'" msgstr "no se sap què fer amb %06o %s «%s»" +#: merge-recursive.c +#, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "No s'ha pogut fusionar el submòdul %s (repositori malmès)" + +#: merge-recursive.c #, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Avançament rà pid del submòdul %s a la següent comissió:" +#: merge-recursive.c #, c-format msgid "Fast-forwarding submodule %s" msgstr "Avançament rà pid al submòdul %s" +#: merge-recursive.c #, c-format msgid "Failed to merge submodule %s (merge following commits not found)" msgstr "" "Ha fallat en fusionar el submòdul %s (no s'ha trobat les comissions següents)" +#: merge-recursive.c #, c-format msgid "Failed to merge submodule %s (not fast-forward)" msgstr "" "S'ha produït un error en fusionar el submòdul %s (sense avançament rà pid)" +#: merge-recursive.c msgid "Found a possible merge resolution for the submodule:\n" msgstr "S'ha trobat una possible resolució de fusió pel submòdul:\n" +#: merge-recursive.c #, c-format msgid "" "If this is correct simply add it to the index for example\n" @@ -17578,18 +22373,30 @@ msgstr "" "\n" "que acceptarà aquest suggeriment.\n" +#: merge-recursive.c #, c-format msgid "Failed to merge submodule %s (multiple merges found)" msgstr "" "S'ha produït un error en fusionar el submòdul %s (s'han trobat múltiples " "fusions)" +#: merge-recursive.c +msgid "failed to execute internal merge" +msgstr "no s'ha pogut executar la fusió interna" + +#: merge-recursive.c +#, c-format +msgid "unable to add %s to database" +msgstr "no s'ha pogut afegir %s a la base de dades" + +#: merge-recursive.c #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" "Error: s'està refusant perdre el fitxer no seguit a %s; en comptes s'ha " "escrit a %s." +#: merge-recursive.c #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " @@ -17598,6 +22405,7 @@ msgstr "" "CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " "s'ha deixat en l'arbre." +#: merge-recursive.c #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " @@ -17606,6 +22414,7 @@ msgstr "" "CONFLICTE: (%s/supressió): %s suprimit en %s i %s a %s en %s. La versió %s " "de %s s'ha deixat en l'arbre." +#: merge-recursive.c #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " @@ -17614,6 +22423,7 @@ msgstr "" "CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " "s'ha deixat en l'arbre a %s." +#: merge-recursive.c #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " @@ -17622,38 +22432,46 @@ msgstr "" "CONFLICTE: (%s/supressió): %s suprimit en %s i %s a %s en %s. La versió %s " "de %s s'ha deixat en l'arbre a %s." +#: merge-recursive.c msgid "rename" msgstr "canvi de nom" +#: merge-recursive.c msgid "renamed" msgstr "canviat de nom" +#: merge-recursive.c #, c-format msgid "Refusing to lose dirty file at %s" msgstr "S'està refusant a perdre el fitxer brut a %s" +#: merge-recursive.c #, c-format msgid "Refusing to lose untracked file at %s, even though it's in the way." msgstr "" "S'està refusant perdre el fitxer no seguit a «%s», malgrat que està en mig " "de l'operació." +#: merge-recursive.c #, c-format msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" msgstr "" "CONFLICTE (canvi de nom/afegiment): Canvi de nom %s->%s a %s. S'ha afegit " "%s a %s" +#: merge-recursive.c #, c-format msgid "%s is a directory in %s adding as %s instead" msgstr "%s és un directori en %s; s'està afegint com a %s en lloc d'això" +#: merge-recursive.c #, c-format msgid "Refusing to lose untracked file at %s; adding as %s instead" msgstr "" "S'està refusant perdre el fitxer no seguit a %s; en comptes, s'està afegint " "com a %s" +#: merge-recursive.c #, c-format msgid "" "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " @@ -17662,15 +22480,18 @@ msgstr "" "CONFLICTE (canvi de nom/canvi de nom): Canvi de nom «%s»->«%s» en la branca " "«%s» canvi de nom «%s»->«%s» en «%s»%s" +#: merge-recursive.c msgid " (left unresolved)" msgstr " (deixat sense resolució)" +#: merge-recursive.c #, c-format msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" msgstr "" "CONFLICTE (canvi de nom/canvi de nom): Canvi de nom %s->%s en %s. Canvi de " "nom %s->%s en %s" +#: merge-recursive.c #, c-format msgid "" "CONFLICT (directory rename split): Unclear where to place %s because " @@ -17681,6 +22502,7 @@ msgstr "" "%s perquè el directori %s s'han canviat de nom a múltiples altres " "directoris, sense una destinació per a la majoria dels fitxers." +#: merge-recursive.c #, c-format msgid "" "CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" @@ -17689,285 +22511,426 @@ msgstr "" "CONFLICTE (canvi de nom/canvi de nom): canvi de nom %s->%s en %s. Canvi de " "nom de directori %s->%s en %s" +#: merge-recursive.c +#, c-format +msgid "cannot read object %s" +msgstr "no es pot llegir l'objecte %s" + +#: merge-recursive.c +#, c-format +msgid "object %s is not a blob" +msgstr "l'objecte %s no és un blob" + +#: merge-recursive.c msgid "modify" msgstr "modificació" +#: merge-recursive.c msgid "modified" msgstr "modificat" +#: merge-recursive.c #, c-format msgid "Skipped %s (merged same as existing)" msgstr "S'ha omès %s (el fusionat és igual a l'existent)" +#: merge-recursive.c #, c-format msgid "Adding as %s instead" msgstr "S'està afegint com a %s en lloc d'això" +#: merge-recursive.c #, c-format msgid "Removing %s" msgstr "S'està eliminant %s" +#: merge-recursive.c msgid "file/directory" msgstr "fitxer/directori" +#: merge-recursive.c msgid "directory/file" msgstr "directori/fitxer" +#: merge-recursive.c #, c-format msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" msgstr "" "CONFLICTE (%s): Hi ha un directori amb nom %s en %s. S'està afegint %s com a " "%s" +#: merge-recursive.c #, c-format msgid "Adding %s" msgstr "S'està afegint %s" +#: merge-recursive.c #, c-format msgid "CONFLICT (add/add): Merge conflict in %s" msgstr "CONFLICTE (afegiment/afegiment): Conflicte de fusió en %s" +#: merge-recursive.c #, c-format msgid "merging of trees %s and %s failed" msgstr "la fusió dels arbres %s i %s ha fallat" +#: merge-recursive.c msgid "Merging:" msgstr "S'està fusionant:" +#: merge-recursive.c #, c-format msgid "found %u common ancestor:" msgid_plural "found %u common ancestors:" msgstr[0] "s'ha trobat %u avantpassat en comú:" msgstr[1] "s'han trobat %u avantpassats en comú:" +#: merge-recursive.c msgid "merge returned no commit" msgstr "la fusió no ha retornat cap comissió" +#: merge-recursive.c #, c-format msgid "Could not parse object '%s'" msgstr "No s'ha pogut analitzar l'objecte «%s»" +#: merge.c msgid "failed to read the cache" msgstr "s'ha produït un error en llegir la memòria cau" +#: midx-write.c +#, c-format +msgid "failed to add packfile '%s'" +msgstr "no s'ha pogut afegir el fitxer de paquet «%s»" + +#: midx-write.c +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "no s'ha pogut obrir l'Ãndex del paquet «%s»" + +#: midx-write.c +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "no s'ha pogut localitzar l'objecte %d en el fitxer de paquet" + +#: midx-write.c +msgid "cannot store reverse index file" +msgstr "no es pot emmagatzemar el fitxer d'Ãndex invers" + +#: midx-write.c +#, c-format +msgid "could not parse line: %s" +msgstr "no s'ha pogut analitzar la lÃnia: %s" + +#: midx-write.c +#, c-format +msgid "malformed line: %s" +msgstr "lÃnia mal formada: %s" + +#: midx-write.c +msgid "could not load pack" +msgstr "no s'ha pogut carregar el paquet" + +#: midx-write.c +#, c-format +msgid "could not open index for %s" +msgstr "s'ha produït un error en obrir l'Ãndex per «%s»" + +#: midx-write.c +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "no s'ha pogut enllaçar «%s» a «%s»" + +#: midx-write.c midx.c +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "no s'ha pogut netejar l'Ãndex multipaquet a %s" + +#: midx-write.c +msgid "cannot write incremental MIDX with bitmap" +msgstr "no es pot escriure un MIDX incremental amb mapa de bits" + +#: midx-write.c +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"s'està ignorant l'Ãndex multipaquet existent; la suma de verificació no " +"coincideix" + +#: midx-write.c +msgid "Adding packfiles to multi-pack-index" +msgstr "S'estan afegint fitxers empaquetats a l'Ãndex multipaquet" + +#: midx-write.c +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "paquet preferit desconegut: «%s»" + +#: midx-write.c +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "no es pot seleccionar un paquet preferit %s sense objectes" + +#: midx-write.c +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "no s'ha vist caure el fitxer empaquetat %s" + +#: midx-write.c +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "el paquet preferit «%s» ha caducat" + +#: midx-write.c +msgid "no pack files to index." +msgstr "no hi ha fitxers empaquetats a indexar." + +#: midx-write.c +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "s'està refusant a escriure el .bitmap multipaquet sense cap objecte" + +#: midx-write.c +msgid "unable to create temporary MIDX layer" +msgstr "no s'ha pogut crear una capa MIDX temporal" + +#: midx-write.c +msgid "could not write multi-pack bitmap" +msgstr "no s'han pogut escriure els mapes de bits dels multipaquets" + +#: midx-write.c +msgid "unable to open multi-pack-index chain file" +msgstr "no s'ha pogut obrir el fitxer de cadenes multi-path-index" + +#: midx-write.c +msgid "unable to rename new multi-pack-index layer" +msgstr "no s'ha pogut canviar el nom de la capa multi-pack-index" + +#: midx-write.c +msgid "could not write multi-pack-index" +msgstr "no s'ha pogut escriure l'Ãndex multipaquet" + +#: midx-write.c +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "no es pot fer caducar paquets d'un multi-pack-index incremental" + +#: midx-write.c +msgid "Counting referenced objects" +msgstr "S'estan comptant els objectes referenciats" + +#: midx-write.c +msgid "Finding and deleting unreferenced packfiles" +msgstr "S'estan cercant i suprimint els fitxers de paquets no referenciats" + +#: midx-write.c +msgid "cannot repack an incremental multi-pack-index" +msgstr "no es pot reempaquetar un multi-pack-index incremental" + +#: midx-write.c +msgid "could not start pack-objects" +msgstr "no s'ha pogut iniciar el pack-objects" + +#: midx-write.c +msgid "could not finish pack-objects" +msgstr "no s'ha pogut finalitzar el pack-objects" + +#: midx.c msgid "multi-pack-index OID fanout is of the wrong size" msgstr "l'OID «fanout» de l'Ãndex multipaquet és d'una mida incorrecta" +#: midx.c #, c-format msgid "" "oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" msgstr "" "oid «fanout» desordenat: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" +#: midx.c msgid "multi-pack-index OID lookup chunk is the wrong size" msgstr "El fragment de cerca OID Ãndex multipaquet és de mida incorrecta" +#: midx.c msgid "multi-pack-index object offset chunk is the wrong size" msgstr "" "el fragment de desplaçament de l'objecte Ãndex multipaquet és d'una mida " "incorrecta" +#: midx.c #, c-format msgid "multi-pack-index file %s is too small" msgstr "el fitxer de l'Ãndex multipaquet %s és massa petit" +#: midx.c #, c-format msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x" msgstr "" "la signatura de l'Ãndex multipaquet 0x%08x no coincideix amb la signatura " "0x%08x" +#: midx.c #, c-format msgid "multi-pack-index version %d not recognized" msgstr "no es reconeix la versió %d de l'Ãndex multipaquet" +#: midx.c #, c-format msgid "multi-pack-index hash version %u does not match version %u" msgstr "" "la versió del resum Ãndex multipaquet %u no coincideix amb la versió %u" +#: midx.c msgid "multi-pack-index required pack-name chunk missing or corrupted" msgstr "" "manca o està malmès el fragment del nom de paquet requerit de l'Ãndex " "multipaquet" +#: midx.c msgid "multi-pack-index required OID fanout chunk missing or corrupted" msgstr "" "manca o està malmès el fragment del «fanout» OID requerit a l'Ãndex " "multipaquet" +#: midx.c msgid "multi-pack-index required OID lookup chunk missing or corrupted" msgstr "" "manca o està malmès el fragment de cerca d'OID necessari a l'Ãndex " "multipaquet" +#: midx.c msgid "multi-pack-index required object offsets chunk missing or corrupted" msgstr "" "manca o està malmès el fragment de l'Ãndex multipaquet dels objectes " "requerits" +#: midx.c msgid "multi-pack-index pack-name chunk is too short" msgstr "el fragment de nom de l'Ãndex multipaquet és massa curt" +#: midx.c #, c-format msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "" "els noms de paquet de l'Ãndex multipaquet estan desordenats «%s» abans de " "«%s»" +#: midx.c +msgid "multi-pack-index chain file too small" +msgstr "el fitxer de cadena multi-pack-index és massa petit" + +#: midx.c +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "el recompte de paquets en el MIDX de base és massa alt: %<PRIuMAX>" + +#: midx.c +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "el recompte de objectes en el MIDX de base és massa alt: %<PRIuMAX>" + +#: midx.c +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "cadena multi-pack-index invà lida: la lÃnia «%s» no és un hash" + +# tots els fitxers multi-pack-index ? +#: midx.c +msgid "unable to find all multi-pack index files" +msgstr "no s'han pogut trobar tots els fitxers d'Ãndex multi-pack" + +#: midx.c +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "" +"posició invà lida de l'objecte MIDX; probablement el MIDX s'ha corromput" + +#: midx.c #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "pack-int-id: %u incorrecte (%u paquets en total)" +#: midx.c msgid "MIDX does not contain the BTMP chunk" msgstr "MIDX no conté el fragment BTMP" +#: midx.c #, c-format msgid "could not load bitmapped pack %<PRIu32>" msgstr "no s'ha pogut carregar el paquet amb bits %<PRIu32>" +#: midx.c msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" msgstr "" "l'Ãndex multipaquet emmagatzema un desplaçament de 64 bits, però off_t és " "massa petit" +#: midx.c msgid "multi-pack-index large offset out of bounds" msgstr "desplaçament gran de l'Ãndex multipaquet està fora dels lÃmits" -#, c-format -msgid "failed to add packfile '%s'" -msgstr "no s'ha pogut afegir el fitxer de paquet «%s»" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "no s'ha pogut obrir l'Ãndex del paquet «%s»" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "no s'ha pogut localitzar l'objecte %d en el fitxer de paquet" - -msgid "cannot store reverse index file" -msgstr "no es pot emmagatzemar el fitxer d'Ãndex invers" - -#, c-format -msgid "could not parse line: %s" -msgstr "no s'ha pogut analitzar la lÃnia: %s" - -#, c-format -msgid "malformed line: %s" -msgstr "lÃnia mal formada: %s" - -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"s'està ignorant l'Ãndex multipaquet existent; la suma de verificació no " -"coincideix" - -msgid "could not load pack" -msgstr "no s'ha pogut carregar el paquet" - -#, c-format -msgid "could not open index for %s" -msgstr "s'ha produït un error en obrir l'Ãndex per «%s»" - -msgid "Adding packfiles to multi-pack-index" -msgstr "S'estan afegint fitxers empaquetats a l'Ãndex multipaquet" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "paquet preferit desconegut: «%s»" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "no es pot seleccionar un paquet preferit %s sense objectes" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "no s'ha vist caure el fitxer empaquetat %s" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "el paquet preferit «%s» ha caducat" - -msgid "no pack files to index." -msgstr "no hi ha fitxers empaquetats a indexar." - -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "s'està refusant a escriure el .bitmap multipaquet sense cap objecte" - -msgid "could not write multi-pack bitmap" -msgstr "no s'han pogut escriure els mapes de bits dels multipaquets" - -msgid "could not write multi-pack-index" -msgstr "no s'ha pogut escriure l'Ãndex multipaquet" - -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "no s'ha pogut netejar l'Ãndex multipaquet a %s" - +#: midx.c msgid "multi-pack-index file exists, but failed to parse" msgstr "" "el fitxer de l'Ãndex multipaquet existeix, però no s'ha pogut analitzar" +#: midx.c msgid "incorrect checksum" msgstr "suma de verificació incorrecta" +#: midx.c msgid "Looking for referenced packfiles" msgstr "S'estan cercant fitxers empaquetats referenciats" +#: midx.c msgid "the midx contains no oid" msgstr "el midx no conté cap oid" +#: midx.c msgid "Verifying OID order in multi-pack-index" msgstr "S'està verificant l'ordre OID a l'Ãndex multipaquet" +#: midx.c #, c-format msgid "oid lookup out of order: oid[%d] = %s >= %s = oid[%d]" msgstr "oid lookup desordenat: oid[%d] = %s >= %s = oid[%d]" +#: midx.c msgid "Sorting objects by packfile" msgstr "S'estan ordenant els objectes per fitxer empaquetats" +#: midx.c msgid "Verifying object offsets" msgstr "S'estan verificant els desplaçaments dels objectes" +#: midx.c #, c-format msgid "failed to load pack entry for oid[%d] = %s" msgstr "no s'ha pogut carregar l'entrada del paquet per a oid[%d] = %s" +#: midx.c #, c-format msgid "failed to load pack-index for packfile %s" msgstr "no s'ha pogut carregar l'Ãndex del paquet per al fitxer empaquetat %s" +#: midx.c #, c-format msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "" "desplaçament incorrecte de l'objecte per a oid[%d] = %s: %<PRIx64> != " "%<PRIx64>" -msgid "Counting referenced objects" -msgstr "S'estan comptant els objectes referenciats" - -msgid "Finding and deleting unreferenced packfiles" -msgstr "S'estan cercant i suprimint els fitxers de paquets no referenciats" - -msgid "could not start pack-objects" -msgstr "no s'ha pogut iniciar el pack-objects" - -msgid "could not finish pack-objects" -msgstr "no s'ha pogut finalitzar el pack-objects" - +#: name-hash.c #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "no s'ha pogut crear el fil «lazy_dir» :%s" +#: name-hash.c #, c-format msgid "unable to create lazy_name thread: %s" msgstr "no s'ha pogut crear un fil «lazy_name»: %s" +#: name-hash.c #, c-format msgid "unable to join lazy_name thread: %s" msgstr "no s'ha pogut unir el fil «lazy_name»: %s" +#: notes-merge.c #, c-format msgid "" "You have not concluded your previous notes merge (%s exists).\n" @@ -17978,17 +22941,21 @@ msgstr "" "Useu «git notes merge --commit» o «git notes merge --abort» per a cometre/" "avortar la fusió prèvia abans de començar una fusió de notes nova." +#: notes-merge.c #, c-format msgid "You have not concluded your notes merge (%s exists)." msgstr "No heu conclòs la vostra fusió de notes (%s existeix)." +#: notes-utils.c msgid "Cannot commit uninitialized/unreferenced notes tree" msgstr "No es pot cometre un arbre de notes no inicialitzat / no referenciat" +#: notes-utils.c #, c-format msgid "Bad notes.rewriteMode value: '%s'" msgstr "Valor de notes.rewriteMode erroni: «%s»" +#: notes-utils.c #, c-format msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" msgstr "S'està refusant reescriure les notes en %s (fora de refs/notes/)" @@ -17997,217 +22964,310 @@ msgstr "S'està refusant reescriure les notes en %s (fora de refs/notes/)" #. the environment variable, the second %s is #. its value. #. +#: notes-utils.c #, c-format msgid "Bad %s value: '%s'" msgstr "Valor erroni de %s: «%s»" +#: object-file-convert.c +msgid "failed to decode tree entry" +msgstr "no s'ha pogut descodificar una entrada d'arbre" + +#: object-file-convert.c +#, c-format +msgid "failed to map tree entry for %s" +msgstr "no s'ha pogut mapar l'entrada d'arbre per a %s" + +#: object-file-convert.c +#, c-format +msgid "bad %s in commit" +msgstr "%s és incorrecte en la comissió" + +#: object-file-convert.c +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "no es pot mapar %s %s en l'objecte de comissió" + +#: object-file-convert.c +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "No s'ha pogut convertir l'objecte de %s a %s" + +#: object-file.c #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "" "no existeix el directori d'objecte %s; comproveu .git/objects/info/alternates" +#: object-file.c #, c-format msgid "unable to normalize alternate object path: %s" msgstr "no s'ha pogut normalitzar el camà a l'objecte alternatiu: %s" +#: object-file.c #, c-format msgid "%s: ignoring alternate object stores, nesting too deep" msgstr "" "%s: s'estan ignorant els emmagatzematges alternatius d'objectes, imbricació " "massa profunda" +#: object-file.c msgid "unable to fdopen alternates lockfile" msgstr "no s'ha pogut fer «fdopen» al fitxer de bloqueig alternatiu" +#: object-file.c msgid "unable to read alternates file" msgstr "no es pot llegir el fitxer «alternates»" +#: object-file.c msgid "unable to move new alternates file into place" msgstr "no s'ha pogut moure el nou fitxer «alternates» al lloc" +#: object-file.c #, c-format msgid "path '%s' does not exist" msgstr "el camà «%s» no existeix" +#: object-file.c #, c-format msgid "reference repository '%s' as a linked checkout is not supported yet." msgstr "" "encara no s'admet el repositori de referència «%s» com a agafament enllaçat." +#: object-file.c #, c-format msgid "reference repository '%s' is not a local repository." msgstr "el repositori de referència «%s» no és un repositori local." +#: object-file.c #, c-format msgid "reference repository '%s' is shallow" msgstr "el repositori de referència «%s» és superficial" +#: object-file.c #, c-format msgid "reference repository '%s' is grafted" msgstr "el repositori de referència «%s» és empeltat" +#: object-file.c #, c-format msgid "could not find object directory matching %s" msgstr "no s'ha pogut trobar el directori de l'objecte que coincideixi amb %s" +#: object-file.c #, c-format msgid "invalid line while parsing alternate refs: %s" msgstr "" "lÃnia no và lida quan s'analitzaven les referències de l'«alternate»: %s" +#: object-file.c #, c-format msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" msgstr "s'està intentant fer mmap %<PRIuMAX> per sobre del lÃmit %<PRIuMAX>" +#: object-file.c #, c-format msgid "mmap failed%s" msgstr "mmap ha fallat%s" +#: object-file.c #, c-format msgid "object file %s is empty" msgstr "el tipus d'objecte %s és buit" +#: object-file.c #, c-format msgid "corrupt loose object '%s'" msgstr "objecte solt corrupte «%s»" +#: object-file.c #, c-format msgid "garbage at end of loose object '%s'" msgstr "brossa al final de l'objecte solt «%s»" +#: object-file.c #, c-format msgid "unable to open loose object %s" msgstr "no s'ha pogut obrir l'objecte solt %s" +#: object-file.c #, c-format msgid "unable to parse %s header" msgstr "no s'ha pogut analitzar la capçalera %s" +#: object-file.c msgid "invalid object type" msgstr "tipus d'objecte és incorrecte" +#: object-file.c #, c-format msgid "unable to unpack %s header" msgstr "no s'ha pogut desempaquetar la capçalera %s" +#: object-file.c #, c-format msgid "header for %s too long, exceeds %d bytes" -msgstr "la capçalera per a %s és massa llarga, supera els %d bytes" +msgstr "la capçalera per a %s és massa llarga, supera els %d octets" +#: object-file.c #, c-format msgid "loose object %s (stored in %s) is corrupt" msgstr "l'objecte solt %s (emmagatzemat a %s) és corrupte" +#: object-file.c #, c-format msgid "replacement %s not found for %s" msgstr "no s'ha trobat el reemplaçament %s per a %s" +#: object-file.c #, c-format msgid "packed object %s (stored in %s) is corrupt" msgstr "l'objecte empaquetat %s (emmagatzemat a %s) és corrupte" +#: object-file.c +#, c-format +msgid "missing mapping of %s to %s" +msgstr "manca el mapatge de %s a %s" + +#: object-file.c +#, c-format +msgid "unable to open %s" +msgstr "no s'ha pogut obrir %s" + +#: object-file.c +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "els fitxers «%s» i «%s» difereixen en el contingut" + +#: object-file.c #, c-format msgid "unable to write file %s" msgstr "no s'ha pogut escriure al fitxer %s" +#: object-file.c #, c-format msgid "unable to set permission to '%s'" msgstr "no s'ha pogut establir el permÃs a «%s»" +#: object-file.c msgid "error when closing loose object file" msgstr "error en tancar el fitxer d'objecte solt" +#: object-file.c #, c-format msgid "insufficient permission for adding an object to repository database %s" msgstr "" "permisos insuficients per a afegir un objecte a la base de dades del " "repositori %s" +#: object-file.c msgid "unable to create temporary file" msgstr "no s'ha pogut crear un fitxer temporal" +#: object-file.c msgid "unable to write loose object file" msgstr "no s'ha pogut escriure el fitxer d'objecte solt" +#: object-file.c #, c-format msgid "unable to deflate new object %s (%d)" msgstr "no s'ha pogut desinflar l'object nou %s (%d)" +#: object-file.c #, c-format msgid "deflateEnd on object %s failed (%d)" msgstr "ha fallat deflateEnd a l'objecte %s(%d)" +#: object-file.c #, c-format msgid "confused by unstable object source data for %s" msgstr "confós per la font de dades inestable de l'objecte per a %s" +#: object-file.c #, c-format msgid "write stream object %ld != %<PRIuMAX>" msgstr "escriu l'objecte de flux %ld != %<PRIuMAX>" +#: object-file.c #, c-format msgid "unable to stream deflate new object (%d)" msgstr "no s'ha pogut desinflar l'object nou (%d)" +#: object-file.c #, c-format msgid "deflateEnd on stream object failed (%d)" msgstr "ha fallat deflateEnd a l'objecte del flux (%d)" +#: object-file.c #, c-format msgid "unable to create directory %s" msgstr "s'ha produït un error en crear el directori %s" +#: object-file.c #, c-format msgid "cannot read object for %s" msgstr "no es pot llegir l'objecte per a %s" +#: object-file.c +#, c-format +msgid "cannot map object %s to %s" +msgstr "no és possible mapar l'objecte %s a %s" + +#: object-file.c #, c-format msgid "object fails fsck: %s" msgstr "l'objecte ha fallat fsck: %s" +#: object-file.c msgid "refusing to create malformed object" msgstr "es rebutja crear un objecte mal format" +#: object-file.c #, c-format msgid "read error while indexing %s" msgstr "error de lectura mentre s'indexava %s" +#: object-file.c #, c-format msgid "short read while indexing %s" msgstr "lectura curta mentre s'indexa %s" +#: object-file.c #, c-format msgid "%s: failed to insert into database" msgstr "%s: no s'han pogut inserir a la base de dades" +#: object-file.c #, c-format msgid "%s: unsupported file type" msgstr "%s: tipus de fitxer no suportat" +#: object-file.c #, c-format msgid "%s is not a valid '%s' object" msgstr "%s no és un objecte de «%s» và lid" -#, c-format -msgid "unable to open %s" -msgstr "no s'ha pogut obrir %s" - +#: object-file.c #, c-format msgid "hash mismatch for %s (expected %s)" msgstr "no coincideix el resum per a %s (s'esperava %s)" +#: object-file.c #, c-format msgid "unable to mmap %s" msgstr "no s'ha pogut fer «mmap» %s" +#: object-file.c #, c-format msgid "unable to unpack header of %s" msgstr "no s'ha pogut desempaquetar la capçalera de %s" +#: object-file.c #, c-format msgid "unable to parse header of %s" msgstr "no s'ha pogut analitzar la capçalera de %s" +#: object-file.c #, c-format msgid "unable to unpack contents of %s" msgstr "no s'han pogut desempaquetar els continguts de %s" @@ -18216,6 +23276,7 @@ msgstr "no s'han pogut desempaquetar els continguts de %s" #. output shown when we cannot look up or parse the #. object in question. E.g. "deadbeef [bad object]". #. +#: object-name.c #, c-format msgid "%s [bad object]" msgstr "%s [objecte incorrecte]" @@ -18225,6 +23286,7 @@ msgstr "%s [objecte incorrecte]" #. * #. "deadbeef commit 2021-01-01 - Some Commit Message" #. +#: object-name.c #, c-format msgid "%s commit %s - %s" msgstr "%s comissió %s - %s" @@ -18240,6 +23302,7 @@ msgstr "%s comissió %s - %s" #. The third argument is the "tag" string #. from object.c. #. +#: object-name.c #, c-format msgid "%s tag %s - %s" msgstr "%s etiqueta %s - %s" @@ -18250,6 +23313,7 @@ msgstr "%s etiqueta %s - %s" #. * #. "deadbeef [bad tag, could not parse it]" #. +#: object-name.c #, c-format msgid "%s [bad tag, could not parse it]" msgstr "%s [etiqueta malmesa, no s'ha pogut analitzar]" @@ -18257,6 +23321,7 @@ msgstr "%s [etiqueta malmesa, no s'ha pogut analitzar]" #. TRANSLATORS: This is a line of ambiguous <type> #. object output. E.g. "deadbeef tree". #. +#: object-name.c #, c-format msgid "%s tree" msgstr "arbre %s" @@ -18264,10 +23329,12 @@ msgstr "arbre %s" #. TRANSLATORS: This is a line of ambiguous <type> #. object output. E.g. "deadbeef blob". #. +#: object-name.c #, c-format msgid "%s blob" msgstr "blob %s" +#: object-name.c #, c-format msgid "short object ID %s is ambiguous" msgstr "l'id d'objecte curt %s és ambigu" @@ -18276,6 +23343,7 @@ msgstr "l'id d'objecte curt %s és ambigu" #. objects composed in show_ambiguous_object(). See #. its "TRANSLATORS" comments for details. #. +#: object-name.c #, c-format msgid "" "The candidates are:\n" @@ -18284,6 +23352,7 @@ msgstr "" "Els candidats són:\n" "%s" +#: object-name.c msgid "" "Git normally never creates a ref that ends with 40 hex characters\n" "because it will be ignored when you just specify 40-hex. These refs\n" @@ -18307,18 +23376,22 @@ msgstr "" "suprimiu-les. Desactiveu aquest missatge executant\n" "«git config advice.objectNameWarning false»" +#: object-name.c #, c-format msgid "log for '%.*s' only goes back to %s" msgstr "registre per a «%.*s» només retorna a %s" +#: object-name.c #, c-format msgid "log for '%.*s' only has %d entries" msgstr "registre per a «%.*s» només té %d entrades" +#: object-name.c #, c-format msgid "path '%s' exists on disk, but not in '%.*s'" msgstr "el camà «%s» existeix al disc, però no a «%.*s»" +#: object-name.c #, c-format msgid "" "path '%s' exists, but not '%s'\n" @@ -18327,10 +23400,12 @@ msgstr "" "el camà «%s» existeix, però no «%s»\n" "consell: volÃeu dir «%.*s:%s» conegut com a «%.*s:./%s»?" +#: object-name.c #, c-format msgid "path '%s' does not exist in '%.*s'" msgstr "el camà «%s» no existeix en «%.*s»" +#: object-name.c #, c-format msgid "" "path '%s' is in the index, but not at stage %d\n" @@ -18339,6 +23414,7 @@ msgstr "" "el camà «%s» està a l'Ãndex, però no a «stage» %d\n" ".consell: volÃeu dir «:%d:%s»?" +#: object-name.c #, c-format msgid "" "path '%s' is in the index, but not '%s'\n" @@ -18347,328 +23423,455 @@ msgstr "" "el camà «%s» està a l'Ãndex, però no a «%s»\n" ".consell: volÃeu dir «:%d:%s» conegut com a «:%d:./%s»?" +#: object-name.c #, c-format msgid "path '%s' exists on disk, but not in the index" msgstr "el camà «%s» existeix al disc, però no a l'Ãndex" +#: object-name.c #, c-format msgid "path '%s' does not exist (neither on disk nor in the index)" msgstr "el camà «%s» no existeix (ni al disc ni a l'Ãndex)" +#: object-name.c msgid "relative path syntax can't be used outside working tree" msgstr "" "la sintaxi de camà relatiu no es pot utilitzar fora de l'arbre de treball" +#: object-name.c #, c-format msgid "<object>:<path> required, only <object> '%s' given" msgstr "<objecte>:<camÃ> requerit, només s'ha donat <objecte> «%s»" +#: object-name.c #, c-format msgid "invalid object name '%.*s'." msgstr "nom d'objecte no và lid «%.*s»." +#: object.c #, c-format msgid "invalid object type \"%s\"" msgstr "tipus d'objecte «%s» no và lid" +#: object.c #, c-format msgid "object %s is a %s, not a %s" msgstr "l'objecte %s és %s, no pas %s" +#: object.c #, c-format msgid "object %s has unknown type id %d" msgstr "l'objecte %s té un identificador de tipus %d desconegut" +#: object.c #, c-format msgid "unable to parse object: %s" msgstr "no s'ha pogut analitzar l'objecte: %s" +#: object.c #, c-format msgid "hash mismatch %s" msgstr "el resum no coincideix %s" +#: pack-bitmap-write.c +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "entrada duplicada en escriure l'Ãndex de mapa de bits: %s" + +#: pack-bitmap-write.c +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "s'ha intentat emmagatzemar una comissió no seleccionada: «%s»" + +#: pack-bitmap-write.c +msgid "too many pseudo-merges" +msgstr "massa pseudo-fusions" + +#: pack-bitmap-write.c msgid "trying to write commit not in index" msgstr "s'està intentant no escriure la comissió a l'Ãndex" +#: pack-bitmap.c msgid "failed to load bitmap index (corrupted?)" msgstr "" "s'ha produït un error en carregar l'Ãndex de mapa de bits (està malmès?)" +#: pack-bitmap.c msgid "corrupted bitmap index (too small)" msgstr "Ãndex de mapa de bits malmès (massa petit)" +#: pack-bitmap.c msgid "corrupted bitmap index file (wrong header)" msgstr "fitxer d'Ãndex de mapa de bits malmès (capçalera incorrecta)" +#: pack-bitmap.c #, c-format msgid "unsupported version '%d' for bitmap index file" msgstr "versió «%d» no admesa per al fitxer d'Ãndex de mapa de bits" +#: pack-bitmap.c msgid "corrupted bitmap index file (too short to fit hash cache)" msgstr "" "fitxer d'Ãndex de mapa de bits malmès (massa curt per a ajustar-se a la " "memòria cau de hash)" +#: pack-bitmap.c msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "" "fitxer d'Ãndex de mapa de bits malmès (massa curt per a ajustar-se a la " "taula de cerca)" +# 2 lÃnies OK? +#: pack-bitmap.c +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"fitxer d'Ãndex de mapes de bits malmès (massa curt per a ajustar-se\n" +"a la capçalera de la taula de pseudo-fusions)" + +# 2 lÃnies OK? +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"fitxer d'Ãndex de mapa de bits malmès (massa curt per a ajustar-se\n" +"a la taula de pseudo-fusions)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "" +"fitxer d'Ãndex de mapa de bits malmès, taula de pseudo-fusions massa curta" + +#: pack-bitmap.c #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "entrada duplicada a l'Ãndex del mapa de bits: «%s»" +#: pack-bitmap.c #, c-format msgid "corrupt ewah bitmap: truncated header for entry %d" msgstr "mapa de bits ewah malmès: capçalera truncada per a l'entrada %d" +#: pack-bitmap.c #, c-format msgid "corrupt ewah bitmap: commit index %u out of range" msgstr "mapa de bits ewah malmès: l'Ãndex de comissió %u està fora de rang" +#: pack-bitmap.c msgid "corrupted bitmap pack index" msgstr "Ãndex de paquets de mapa de bits malmès" +#: pack-bitmap.c msgid "invalid XOR offset in bitmap pack index" msgstr "el desplaçament XOR a l'Ãndex de mapa de bits no és và lid" +#: pack-bitmap.c msgid "cannot fstat bitmap file" msgstr "no es pot fer fstat en el fitxer de mapa de bits" +#: pack-bitmap.c msgid "checksum doesn't match in MIDX and bitmap" msgstr "la suma de verificació no coincideix amb el MIDX i el mapa de bits" +#: pack-bitmap.c msgid "multi-pack bitmap is missing required reverse index" msgstr "falta l'Ãndex invers necessari al mapa de bits multipaquet" +#: pack-bitmap.c #, c-format msgid "could not open pack %s" msgstr "no s'ha pogut obrir el paquet %s" +#: pack-bitmap.c t/helper/test-read-midx.c msgid "could not determine MIDX preferred pack" msgstr "no s'ha pogut determinar el paquet preferit MIDX" +#: pack-bitmap.c #, c-format msgid "preferred pack (%s) is invalid" msgstr "el paquet preferit (%s) no és và lid" +#: pack-bitmap.c msgid "corrupt bitmap lookup table: triplet position out of index" msgstr "" "taula de cerca de mapa de bits malmesa: posició la tripleta fora de l'Ãndex" +#: pack-bitmap.c msgid "corrupt bitmap lookup table: xor chain exceeds entry count" msgstr "" "taula de cerca de mapa de bits malmesa: la cadena xor excedeix el nombre " "d'entrades" +#: pack-bitmap.c #, c-format msgid "corrupt bitmap lookup table: commit index %u out of range" msgstr "" "taula de cerca de mapa de bits malmesa: l'Ãndex de comissió %u està fora de " "rang" +#: pack-bitmap.c #, c-format msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\"" msgstr "" "mapa de bits ewah malmès: capçalera truncada per al mapa de bits de la " "comissió «%s»" +#: pack-bitmap.c #, c-format msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "" "no s'ha pogut carregar el paquet: «%s», s'està inhabilitant lareutilització " "de paquets" +# s'inhabilita / s'està inhabilitant? +#: pack-bitmap.c +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "no s'ha pogut calcular el paquet preferit, s'inhabilita pack-reuse" + +#: pack-bitmap.c #, c-format msgid "object '%s' not found in type bitmaps" msgstr "no s'ha trobat l'objecte «%s» als tipus de mapes de bits" +#: pack-bitmap.c #, c-format msgid "object '%s' does not have a unique type" msgstr "l'objecte «%s» no té un tipus únic" +#: pack-bitmap.c #, c-format msgid "object '%s': real type '%s', expected: '%s'" msgstr "objecte «%s»: tipus real «%s», s'esperava: «%s»" +#: pack-bitmap.c #, c-format msgid "object not in bitmap: '%s'" msgstr "objecte no trobat al mapa de bits: «%s»" +#: pack-bitmap.c msgid "failed to load bitmap indexes" msgstr "s'ha produït un error en carregar l'Ãndex de mapa de bits" +#: pack-bitmap.c msgid "you must specify exactly one commit to test" msgstr "heu d'especificar exactament una comissió a provar" +#: pack-bitmap.c #, c-format msgid "commit '%s' doesn't have an indexed bitmap" msgstr "la comissió «%s» no té un mapa de bits indexat" +#: pack-bitmap.c msgid "mismatch in bitmap results" msgstr "no coincideix en els resultats del mapa de bits" +#: pack-bitmap.c +#, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "l'Ãndex de pseudo-fusions és fora de rang (%<PRIu32> >= %<PRIuMAX>)" + +#: pack-bitmap.c #, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "no s'ha pogut trobar «%s» al paquet «%s» al desplaçament %<PRIuMAX>" +#: pack-bitmap.c #, c-format msgid "unable to get disk usage of '%s'" msgstr "no s'ha pogut obtenir l'ús del disc de «%s»" +#: pack-bitmap.c #, c-format msgid "bitmap file '%s' has invalid checksum" msgstr "el fitxer de mapa de bits «%s» té una suma de verificació no và lida" +#: pack-mtimes.c #, c-format msgid "mtimes file %s is too small" msgstr "el fitxer mtimes %s és massa petit" +#: pack-mtimes.c #, c-format msgid "mtimes file %s has unknown signature" msgstr "el fitxer mtimes %s té una signatura desconeguda" +#: pack-mtimes.c #, c-format msgid "mtimes file %s has unsupported version %<PRIu32>" msgstr "el fitxer mtimes %s té la versió %<PRIu32> no admesa" +#: pack-mtimes.c #, c-format msgid "mtimes file %s has unsupported hash id %<PRIu32>" msgstr "el fitxer mtimes %s té un ID de resum %<PRIu32> no admès" +#: pack-mtimes.c #, c-format msgid "mtimes file %s is corrupt" msgstr "el fitxer mtimes %s està malmès" +#: pack-revindex.c #, c-format msgid "reverse-index file %s is too small" msgstr "el fitxer d'Ãndex invers %s és massa petit" +#: pack-revindex.c #, c-format msgid "reverse-index file %s is corrupt" msgstr "el fitxer d'Ãndex invers %s està malmès" +#: pack-revindex.c #, c-format msgid "reverse-index file %s has unknown signature" msgstr "el fitxer d'Ãndex invers %s té una signatura desconeguda" +#: pack-revindex.c #, c-format msgid "reverse-index file %s has unsupported version %<PRIu32>" msgstr "el fitxer d'Ãndex invers %s té la versió %<PRIu32> no admesa" +#: pack-revindex.c #, c-format msgid "reverse-index file %s has unsupported hash id %<PRIu32>" msgstr "el fitxer d'Ãndex invers %s té un ID de resum %<PRIu32> no admès" +#: pack-revindex.c msgid "invalid checksum" msgstr "suma de verificació no và lida" +#: pack-revindex.c #, c-format msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>" msgstr "" "posició no và lida de l'Ãndex de reversió a %<PRIu64>: %<PRIu32> != %<PRIu32>" +#: pack-revindex.c msgid "multi-pack-index reverse-index chunk is the wrong size" msgstr "" "el fragment de l'index invers de l'Ãndex multipaquet és de mida incorrecta" +#: pack-revindex.c msgid "could not determine preferred pack" msgstr "no s'ha pogut determinar el paquet preferit" +#: pack-write.c msgid "cannot both write and verify reverse index" msgstr "no es pot escriure i verificar l'Ãndex invers" +#: pack-write.c #, c-format msgid "could not stat: %s" msgstr "no s'ha pogut fer stat a: %s" +#: pack-write.c #, c-format msgid "failed to make %s readable" msgstr "s'ha produït un error en fer %s llegible" +#: pack-write.c #, c-format msgid "could not write '%s' promisor file" msgstr "no s'ha pogut escriure «%s» al fitxer «promisor»" +#: packfile.c msgid "offset before end of packfile (broken .idx?)" msgstr "desplaçament abans de la fi del fitxer de paquet (.idx trencat?)" +#: packfile.c #, c-format msgid "packfile %s cannot be mapped%s" msgstr "el fitxer de paquet %s no es pot mapar%s" +#: packfile.c #, c-format msgid "offset before start of pack index for %s (corrupt index?)" msgstr "" "desplaçament abans d'inici d'Ãndex de paquet per a %s (Ãndex corromput?)" +#: packfile.c #, c-format msgid "offset beyond end of pack index for %s (truncated index?)" msgstr "" "desplaçament més enllà de la fi d'Ãndex de paquet per a %s (Ãndex truncat?)" +#: parse-options-cb.c #, c-format msgid "malformed expiration date '%s'" msgstr "data de venciment «%s» mal formada" +#: parse-options-cb.c #, c-format msgid "option `%s' expects \"always\", \"auto\", or \"never\"" msgstr "l'opció «%s» espera «always», «auto» o «never»" +#: parse-options-cb.c #, c-format msgid "malformed object name '%s'" msgstr "nom d'objecte «%s» mal format" +#: parse-options-cb.c #, c-format msgid "option `%s' expects \"%s\" or \"%s\"" msgstr "l'opció «%s» espera «%s» o «%s»" +#: parse-options.c #, c-format msgid "%s requires a value" msgstr "%s requereix un valor" +#: parse-options.c #, c-format msgid "%s takes no value" msgstr "%s no accepta cap valor" +#: parse-options.c #, c-format msgid "%s isn't available" msgstr "%s no és disponible" +#: parse-options.c #, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "%s espera un valor enter no negatiu amb un sufix opcional k/m/g" +#: parse-options.c #, c-format msgid "ambiguous option: %s (could be --%s%s or --%s%s)" msgstr "opció ambigua: %s (pot ser --%s%s o --%s%s)" +#: parse-options.c #, c-format msgid "did you mean `--%s` (with two dashes)?" msgstr "voleu dir «--%s» (amb dos guionets)?" +#: parse-options.c #, c-format msgid "alias of --%s" msgstr "à lies de --%s" +#: parse-options.c msgid "need a subcommand" msgstr "cal una subordre" +#: parse-options.c #, c-format msgid "unknown option `%s'" msgstr "opció desconeguda «%s»" +#: parse-options.c #, c-format msgid "unknown switch `%c'" msgstr "opció «%c» desconeguda" +#: parse-options.c #, c-format msgid "unknown non-ascii option in string: `%s'" msgstr "opció no ascii desconeguda en la cadena: «%s»" +#: parse-options.c msgid "..." msgstr "..." +#: parse-options.c #, c-format msgid "usage: %s" msgstr "ús: %s" @@ -18676,6 +23879,7 @@ msgstr "ús: %s" #. TRANSLATORS: the colon here should align with the #. one in "usage: %s" translation. #. +#: parse-options.c #, c-format msgid " or: %s" msgstr " o: %s" @@ -18699,83 +23903,105 @@ msgstr " o: %s" #. translated) N_() usage string, which contained embedded #. newlines before we split it up. #. +#: parse-options.c #, c-format msgid "%*s%s" msgstr "%*s%s" +#: parse-options.c #, c-format msgid " %s" msgstr " %s" +#: parse-options.c msgid "-NUM" msgstr "-NUM" +#: parse-options.c #, c-format msgid "opposite of --no-%s" msgstr "oposat a --no-%s" +#: parse-options.h msgid "expiry-date" msgstr "data-de-caducitat" +#: parse-options.h msgid "no-op (backward compatibility)" msgstr "operació nul·la (per a compatibilitat amb versions anteriors)" +#: parse-options.h msgid "be more verbose" msgstr "sigues més detallat" +#: parse-options.h msgid "be more quiet" msgstr "sigues més discret" +#: parse-options.h msgid "use <n> digits to display object names" msgstr "usa <n> xifres per a mostrar els noms d'objecte" +#: parse-options.h msgid "prefixed path to initial superproject" msgstr "camà prefixat al superprojecte inicial" +#: parse-options.h msgid "how to strip spaces and #comments from message" msgstr "com suprimir els espais i #comentaris del missatge" +#: parse-options.h msgid "read pathspec from file" msgstr "llegeix l'especificació del camà del fitxer" +#: parse-options.h msgid "" "with --pathspec-from-file, pathspec elements are separated with NUL character" msgstr "" "amb --pathspec-from-file els elements d'especificació del camà estan " "separats amb el carà cter NUL" +#: parse.c #, c-format msgid "bad boolean environment value '%s' for '%s'" msgstr "el valor «%s» booleà de l'entorn és incorrecte per a «%s»" +#: parse.c #, c-format msgid "failed to parse %s" msgstr "s'ha produït un error en analitzar %s" +#: path.c #, c-format msgid "Could not make %s writable by group" msgstr "No s'ha pogut fer %s escrivible pel grup" +#: pathspec.c msgid "Escape character '\\' not allowed as last character in attr value" msgstr "" "El carà cter d'escapament «\\» no està permès com a últim carà cter en un " "valor d'un atribut" +#: pathspec.c msgid "Only one 'attr:' specification is allowed." msgstr "Només es permet una especificació «attr:»." +#: pathspec.c msgid "attr spec must not be empty" msgstr "una especificació d'atribut no pot estar buida" +#: pathspec.c #, c-format msgid "invalid attribute name %s" msgstr "nom d'atribut no và lid %s" +#: pathspec.c msgid "global 'glob' and 'noglob' pathspec settings are incompatible" msgstr "" "els parà metres d'especificació de camà «glob» i «noglob» globals són " "incompatibles" +#: pathspec.c msgid "" "global 'literal' pathspec setting is incompatible with all other global " "pathspec settings" @@ -18783,138 +24009,273 @@ msgstr "" "el parà metre d'especificació de camà «literal» global és incompatible amb " "tots els altres parà metres d'especificació de camà globals" +#: pathspec.c msgid "invalid parameter for pathspec magic 'prefix'" msgstr "parà metre no và lid per a la mà gia d'especificació de camà «prefix»" +#: pathspec.c #, c-format msgid "Invalid pathspec magic '%.*s' in '%s'" msgstr "Mà gia d'especificació de camà no và lida «%.*s» en «%s»" +#: pathspec.c #, c-format msgid "Missing ')' at the end of pathspec magic in '%s'" msgstr "«)» mancant al final de la mà gia d'especificació de camà en «%s»" +#: pathspec.c #, c-format msgid "Unimplemented pathspec magic '%c' in '%s'" msgstr "Mà gia d'especificació de camà no implementada «%c» en «%s»" +#: pathspec.c #, c-format msgid "%s: 'literal' and 'glob' are incompatible" msgstr "%s: «literal» i «glob» són incompatibles" +#: pathspec.c #, c-format msgid "'%s' is outside the directory tree" msgstr "«%s» és fora de l'arbre de directoris" +#: pathspec.c #, c-format msgid "%s: '%s' is outside repository at '%s'" msgstr "%s: «%s» està fora del repositori en «%s»" +#: pathspec.c #, c-format msgid "'%s' (mnemonic: '%c')" msgstr "«%s» (mnemònic: «%c»)" +#: pathspec.c #, c-format msgid "%s: pathspec magic not supported by this command: %s" msgstr "" "%s: aquesta ordre no està admesa amb la mà gia d'especificació de camÃ: %s" +#: pathspec.c #, c-format msgid "pathspec '%s' is beyond a symbolic link" msgstr "l'especificació de camà «%s» és més enllà d'un enllaç simbòlic" +#: pathspec.c #, c-format msgid "line is badly quoted: %s" msgstr "la lÃnia no està ben envoltada per cometes: %s" +#: pkt-line.c msgid "unable to write flush packet" msgstr "no s'ha pogut escriure el paquet de buidatge" +#: pkt-line.c msgid "unable to write delim packet" msgstr "no s'ha pogut escriure el paquet delim" +#: pkt-line.c msgid "unable to write response end packet" msgstr "no s'ha pogut escriure el paquet de final de resposta" +#: pkt-line.c msgid "flush packet write failed" msgstr "s'ha produït un error en escriure el paquet de buidatge" +#: pkt-line.c msgid "protocol error: impossibly long line" msgstr "error de protocol: longitud de lÃnia impossible" +#: pkt-line.c msgid "packet write with format failed" msgstr "ha fallat l'escriptura del paquet amb format" +#: pkt-line.c msgid "packet write failed - data exceeds max packet size" msgstr "" "no s'ha pogut escriure el paquet - les dades excedeixen la mida mà xima del " "paquet" +#: pkt-line.c #, c-format msgid "packet write failed: %s" msgstr "no s'ha pogut escriure el paquet: %s" +#: pkt-line.c msgid "read error" msgstr "error de lectura" +#: pkt-line.c msgid "the remote end hung up unexpectedly" msgstr "el remot ha penjat inesperadament" +#: pkt-line.c #, c-format msgid "protocol error: bad line length character: %.4s" msgstr "error de protocol: carà cter de longitud de lÃnia erroni: %.4s" +#: pkt-line.c #, c-format msgid "protocol error: bad line length %d" msgstr "error de protocol: longitud de lÃnia errònia %d" +#: pkt-line.c sideband.c #, c-format msgid "remote error: %s" msgstr "error remot: %s" +#: preload-index.c msgid "Refreshing index" msgstr "S'està actualitzant l'Ãndex" +#: preload-index.c #, c-format msgid "unable to create threaded lstat: %s" msgstr "no s'han pogut crear lstat amb fils %s" +#: pretty.c msgid "unable to parse --pretty format" msgstr "no s'ha pogut analitzar el format --pretty" +# lazy → tardà as in “lazy evaluation†+# 2 lÃnies OK? +#: promisor-remote.c +msgid "lazy fetching disabled; some objects may not be available" +msgstr "" +"s'ha inhabilitat l'obtenció tardana; por ser que alguns objectes\n" +"no estiguin disponibles" + +#: promisor-remote.c msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: no es pot bifurcar el subprocés d'obtenció" +#: promisor-remote.c msgid "promisor-remote: could not write to fetch subprocess" msgstr "promisor-remote: no s'ha pogut escriure per al subprocés d'obtenció" +#: promisor-remote.c msgid "promisor-remote: could not close stdin to fetch subprocess" msgstr "promisor-remote: no s'ha pogut tancar stdin al subprocés d'obtenció" +#: promisor-remote.c #, c-format msgid "promisor remote name cannot begin with '/': %s" msgstr "el nom remot «promisor» no pot començar amb «/»: %s" +#: promisor-remote.c #, c-format msgid "could not fetch %s from promisor remote" msgstr "no s'ha pogut obtenir «%s» del «promisor» remot" +#: protocol-caps.c msgid "object-info: expected flush after arguments" msgstr "object-info: s'esperava una neteja després dels arguments" +#: prune-packed.c msgid "Removing duplicate objects" msgstr "S'estan eliminant els objectes duplicats" +#: pseudo-merge.c +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "" +"no s'ha pogut carregar l'expressió regular de pseudo-fusió per a %s: «%s»" + +# gerundi → futur? +# default → valor predeterminat? +#: pseudo-merge.c +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s ha de ser no negatiu, s'usarà el valor predeterminat" + +# gerundi → futur? +# default → valor predeterminat? +#: pseudo-merge.c +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s ha d'estar entre 0 i 1, s'usarà el valor predeterminat" + +# gerundi → futur? +# default → valor predeterminat? +#: pseudo-merge.c +#, c-format +msgid "%s must be positive, using default" +msgstr "%s ha de ser positiu, s'usarà el valor predeterminat" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "manca un patró requerit al grup de pseudo-fusió «%s»" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"el grup de pseudo-fusió «%s» té un llindar inestable abans de l'estable" + +#: pseudo-merge.c +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"l'expressió regular de pseudo-fusions procedent de la configuració\n" +"té massa grups de captura (mà xim=%<PRIuMAX>)" + +# lectura ampliada o pseudo-fusions ampliades? +# read → lectura / llegit? +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"la lectura de pseudo-fusions ampliades és fora de rang (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"l'entrada de pseudo-fusions ampliades és massa curta (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"no s'ha pogut trobar una pseudo-fusió per a la comissió %s\n" +"a la posició %<PRIuMAX>" + +# consulta ampliada o pseudo-fusions ampliades? +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"la consulta de pseudo-fusions ampliades és fora de rang (%<PRIu32> >= " +"%<PRIu32>)" + +# read → lectura? +#: pseudo-merge.c +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "lectura fora de rang: (%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "" +"no s'ha pogut llegir la taula de pseudo-fusions ampliada per a la comissió %s" + +#: range-diff.c msgid "could not start `log`" msgstr "no s'ha pogut iniciar «log»" +#: range-diff.c msgid "could not read `log` output" msgstr "no s'ha pogut llegir la sortida de «log»" +#: range-diff.c sequencer.c #, c-format msgid "could not parse commit '%s'" msgstr "no s'ha pogut analitzar la comissió «%s»" +#: range-diff.c #, c-format msgid "" "could not parse first line of `log` output: did not start with 'commit ': " @@ -18923,51 +24284,64 @@ msgstr "" "no s'ha pogut analitzar la primera lÃnia de la sortida «log»: no començava " "amb «commit»: «%s»" +#: range-diff.c #, c-format msgid "could not parse git header '%.*s'" msgstr "no s'ha pogut llegir la capçalera de la gif «%.*s»" +#: range-diff.c msgid "failed to generate diff" msgstr "s'ha produït un error en generar el diff" +#: range-diff.c #, c-format msgid "could not parse log for '%s'" msgstr "no s'ha pogut llegir el fitxer de registre per a «%s»" +#: reachable.c #, c-format msgid "invalid extra cruft tip: '%s'" msgstr "punta extra extra no và lida: «%s»" +#: reachable.c msgid "unable to enumerate additional recent objects" msgstr "no s'han pogut enumerar els objectes recents addicionals" +#: read-cache.c #, c-format msgid "will not add file alias '%s' ('%s' already exists in index)" msgstr "no s'afegirà l'à lies «%s»: («%s» ja existeix en l'Ãndex)" +#: read-cache.c msgid "cannot create an empty blob in the object database" msgstr "no es pot crear un blob buit a la base de dades d'objectes" +#: read-cache.c #, c-format msgid "%s: can only add regular files, symbolic links or git-directories" msgstr "" "%s: només pot afegir fitxers normals, enllaços simbòlics o directoris git" +#: read-cache.c #, c-format msgid "unable to index file '%s'" msgstr "no es pot llegir indexar el fitxer «%s»" +#: read-cache.c #, c-format msgid "unable to add '%s' to index" msgstr "no s'ha pogut afegir «%s» a l'Ãndex" +#: read-cache.c #, c-format msgid "'%s' appears as both a file and as a directory" msgstr "«%s» apareix com a fitxer i com a directori" +#: read-cache.c msgid "Refresh index" msgstr "Actualitza l'Ãndex" +#: read-cache.c #, c-format msgid "" "index.version set, but the value is invalid.\n" @@ -18976,6 +24350,7 @@ msgstr "" "index.version està establerta, però el valor no és và lid.\n" "S'està usant la versió %i" +#: read-cache.c #, c-format msgid "" "GIT_INDEX_VERSION set, but the value is invalid.\n" @@ -18984,114 +24359,143 @@ msgstr "" "GIT_INDEX_VERSION està establerta, però el valor no és và lid.\n" "S'està usant la versió %i" +#: read-cache.c #, c-format msgid "bad signature 0x%08x" msgstr "signatura malmesa 0x%08x" +#: read-cache.c #, c-format msgid "bad index version %d" msgstr "versió d'Ãndex incorrecta %d" +#: read-cache.c msgid "bad index file sha1 signature" msgstr "signatura sha1 malmesa al fitxer d'Ãndex" +#: read-cache.c #, c-format msgid "index uses %.4s extension, which we do not understand" msgstr "l'Ãndex usa l'extensió %.4s, que no es pot entendre" +#: read-cache.c #, c-format msgid "ignoring %.4s extension" msgstr "s'està ignorant l'extensió %.4s" +#: read-cache.c #, c-format msgid "unknown index entry format 0x%08x" msgstr "format d'entrada d'Ãndex desconeguda «0x%08x»" +#: read-cache.c #, c-format msgid "malformed name field in the index, near path '%s'" msgstr "camp del nom mal formatat l'Ãndex, camà a prop «%s»" +#: read-cache.c msgid "unordered stage entries in index" msgstr "entrades «stage» no ordenades en l'Ãndex" +#: read-cache.c #, c-format msgid "multiple stage entries for merged file '%s'" msgstr "múltiples entrades «stage» per al fitxer fusionat «%s»" +#: read-cache.c #, c-format msgid "unordered stage entries for '%s'" msgstr "entrades «stage» no ordenades per a «%s»" +#: read-cache.c #, c-format msgid "unable to create load_cache_entries thread: %s" msgstr "no s'ha pogut crear fil «load_cache_entries»: %s" +#: read-cache.c #, c-format msgid "unable to join load_cache_entries thread: %s" msgstr "no s'ha pogut unir al fil «load_cache_entries»: %s" +#: read-cache.c #, c-format msgid "%s: index file open failed" msgstr "%s: ha fallat l'obertura del fitxer d'Ãndex" +#: read-cache.c #, c-format msgid "%s: cannot stat the open index" msgstr "%s: no es pot fer «stat» a l'Ãndex obert" +#: read-cache.c #, c-format msgid "%s: index file smaller than expected" msgstr "%s: fitxer d'Ãndex més petit que s'esperava" +#: read-cache.c #, c-format msgid "%s: unable to map index file%s" msgstr "%s: no es pot mapar el fitxer d'Ãndex%s" +#: read-cache.c #, c-format msgid "unable to create load_index_extensions thread: %s" msgstr "no s'ha pogut crear un fil «load_index_extensions»: %s" +#: read-cache.c #, c-format msgid "unable to join load_index_extensions thread: %s" msgstr "no s'ha pogut unir un fil «load_index_extensions»: %s" +#: read-cache.c #, c-format msgid "could not freshen shared index '%s'" msgstr "no s'ha pogut refrescar l'Ãndex compartit «%s»" +#: read-cache.c #, c-format msgid "broken index, expect %s in %s, got %s" msgstr "Ãndex malmès, s'esperava %s a %s, s'ha rebut %s" +#: read-cache.c msgid "cannot write split index for a sparse index" msgstr "no es pot escriure l'Ãndex dividit per a un Ãndex dispers" +#: read-cache.c msgid "failed to convert to a sparse-index" msgstr "s'ha produït un error en convertir a un Ãndex dispers" +#: read-cache.c #, c-format msgid "unable to open git dir: %s" msgstr "no s'ha pogut obrir el directori git: %s" +#: read-cache.c #, c-format msgid "unable to unlink: %s" msgstr "no s'ha pogut desenllaçar: %s" +#: read-cache.c #, c-format msgid "cannot fix permission bits on '%s'" msgstr "no s'han pogut corregir els bits de permisos en «%s»" +#: read-cache.c #, c-format msgid "%s: cannot drop to stage #0" msgstr "%s: no es pot baixar fins al «stage» #0" +#: read-cache.c #, c-format msgid "unexpected diff status %c" msgstr "estat de diff inesperat %c" +#: read-cache.c #, c-format msgid "remove '%s'\n" msgstr "elimina «%s»\n" +#: rebase-interactive.c msgid "" "You can fix this with 'git rebase --edit-todo' and then run 'git rebase --" "continue'.\n" @@ -19101,6 +24505,7 @@ msgstr "" "continue».\n" "O bé, podeu avortar el «rebase» amb «git rebase --abort».\n" +#: rebase-interactive.c #, c-format msgid "" "unrecognized setting %s for option rebase.missingCommitsCheck. Ignoring." @@ -19108,6 +24513,7 @@ msgstr "" "no s'ha reconegut el parà metre %s per rebase.missingCommitsCheck. S'està " "ignorant." +#: rebase-interactive.c msgid "" "\n" "Commands:\n" @@ -19160,20 +24566,22 @@ msgstr "" " (o lÃnia única, si no hi ha cap comissió de fusió original " "especificada).\n" " Useu -c <comissió> per a reescriure el missatge de la comissió.\n" -"u, update-ref <ref> = segueix un marcador de posició per a actualitzar " -"<ref>\n" +"u, update-ref <referència> = segueix un marcador de posició per a " +"actualitzar <ref>\n" " a aquesta posició en les comissions noves. La <ref> " "s'actualitza\n" " al final del «rebase»\n" "\n" "Es pot canviar l'ordre d'aquestes lÃnies; s'executen de dalt a baix.\n" +#: rebase-interactive.c #, c-format msgid "Rebase %s onto %s (%d command)" msgid_plural "Rebase %s onto %s (%d commands)" msgstr[0] "Fes «rebase» de %s a %s (%d ordre)" msgstr[1] "Fes «rebase» de %s a %s (%d ordres)" +#: rebase-interactive.c msgid "" "\n" "Do not remove any line. Use 'drop' explicitly to remove a commit.\n" @@ -19182,6 +24590,7 @@ msgstr "" "No elimineu cap lÃnia. Useu «drop» explÃcitament per a eliminar una " "comissió.\n" +#: rebase-interactive.c msgid "" "\n" "If you remove a line here THAT COMMIT WILL BE LOST.\n" @@ -19189,6 +24598,7 @@ msgstr "" "\n" "Si elimineu una lÃnia aquÃ, ES PERDRÀ AQUELLA COMISSIÓ.\n" +#: rebase-interactive.c msgid "" "\n" "You are editing the todo file of an ongoing interactive rebase.\n" @@ -19202,19 +24612,22 @@ msgstr "" " git rebase --continue\n" "\n" +#: rebase-interactive.c msgid "" "\n" "However, if you remove everything, the rebase will be aborted.\n" "\n" msgstr "" "\n" -"No obstant això, si elimineu tot, s'avortarà el «rebase».\n" +"No obstant això, si ho elimineu tot, s'avortarà el «rebase».\n" "\n" +#: rebase-interactive.c #, c-format msgid "could not write '%s'." msgstr "no s'ha pogut escriure a «%s»." +#: rebase-interactive.c #, c-format msgid "" "Warning: some commits may have been dropped accidentally.\n" @@ -19224,6 +24637,7 @@ msgstr "" "accidentalment.\n" "Les comissions descartades (més nova a més vella):\n" +#: rebase-interactive.c #, c-format msgid "" "To avoid this message, use \"drop\" to explicitly remove a commit.\n" @@ -19240,113 +24654,146 @@ msgstr "" "d'advertències.\n" "Els comportaments possibles són: ignore, warn, error.\n" +#: rebase.c #, c-format msgid "%s: 'preserve' superseded by 'merges'" msgstr "%s: «conserva» substituït per «fusiona»" +#: ref-filter.c wt-status.c msgid "gone" msgstr "no hi és" +#: ref-filter.c #, c-format msgid "ahead %d" msgstr "davant per %d" +#: ref-filter.c #, c-format msgid "behind %d" msgstr "darrere per %d" +#: ref-filter.c #, c-format msgid "ahead %d, behind %d" msgstr "davant per %d, darrere per %d" +#: ref-filter.c #, c-format msgid "%%(%.*s) does not take arguments" msgstr "%%(%.*s) no accepta arguments" +#: ref-filter.c #, c-format msgid "unrecognized %%(%.*s) argument: %s" msgstr "argument %%(%.*s) desconegut: %s" +#: ref-filter.c #, c-format msgid "expected format: %%(color:<color>)" msgstr "format esperat: %%(color:<color>)" +#: ref-filter.c #, c-format msgid "unrecognized color: %%(color:%s)" msgstr "color no reconegut: %%(color:%s)" +#: ref-filter.c #, c-format msgid "Integer value expected refname:lstrip=%s" msgstr "Valor enter esperat pel nom de referència:lstrip=%s" +#: ref-filter.c #, c-format msgid "Integer value expected refname:rstrip=%s" msgstr "Valor enter esperat pel nom de referència:rstrip=%s" +#: ref-filter.c #, c-format msgid "expected %%(trailers:key=<value>)" -msgstr "s'esperava %%(trailers:key=<value>)" +msgstr "s'esperava %%(trailers:key=<valor>)" +#: ref-filter.c #, c-format msgid "unknown %%(trailers) argument: %s" msgstr "argument %%(trailers) desconegut: %s" +#: ref-filter.c #, c-format msgid "positive value expected contents:lines=%s" msgstr "valor positiu esperat conté:lines=%s" +#: ref-filter.c #, c-format msgid "argument expected for %s" msgstr "s'esperava un argument per a %s" +#: ref-filter.c #, c-format msgid "positive value expected %s=%s" msgstr "valor positiu esperat %s=%s" +#: ref-filter.c #, c-format msgid "cannot fully parse %s=%s" msgstr "no es pot analitzar completament %s=%s" +#: ref-filter.c #, c-format msgid "value expected %s=" msgstr "s'esperava un valor %s=" +#: ref-filter.c #, c-format msgid "positive value expected '%s' in %%(%s)" msgstr "valor positiu esperat «%s» a %%(%s)" +#: ref-filter.c #, c-format msgid "expected format: %%(align:<width>,<position>)" msgstr "format esperat: %%(align:<amplada>,<posició>)" +#: ref-filter.c #, c-format msgid "unrecognized position:%s" msgstr "posició no reconeguda:%s" +#: ref-filter.c #, c-format msgid "unrecognized width:%s" msgstr "amplada no reconeguda:%s" +#: ref-filter.c #, c-format msgid "unrecognized %%(%s) argument: %s" msgstr "argument %%(%s) desconegut: %s" +#: ref-filter.c #, c-format msgid "positive width expected with the %%(align) atom" msgstr "amplada positiva esperada amb l'à tom %%(align)" +#: ref-filter.c #, c-format msgid "expected format: %%(ahead-behind:<committish>)" msgstr "format esperat: %%(ahead-behind:<committish>)" +#: ref-filter.c +#, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "format esperat: %%(is-base:<committish>)" + +#: ref-filter.c #, c-format msgid "malformed field name: %.*s" msgstr "nom de camp mal format: %.*s" +#: ref-filter.c #, c-format msgid "unknown field name: %.*s" msgstr "nom de camp desconegut: %.*s" +#: ref-filter.c #, c-format msgid "" "not a git repository, but the field '%.*s' requires access to object data" @@ -19354,117 +24801,147 @@ msgstr "" "no és un repositori git, però el camp «%.*s» requereix accés a les dades de " "l'objecte" +#: ref-filter.c #, c-format msgid "format: %%(%s) atom used without a %%(%s) atom" msgstr "format: l'à tom %%(%s) usat sense un à tom %%(%s)" +#: ref-filter.c #, c-format msgid "format: %%(then) atom used more than once" msgstr "format: s'ha usat l'à tom %%(then) més d'un cop" +#: ref-filter.c #, c-format msgid "format: %%(then) atom used after %%(else)" msgstr "format: s'ha usat l'à tom %%(then) després de %%(else)" +#: ref-filter.c #, c-format msgid "format: %%(else) atom used more than once" msgstr "format: s'ha usat l'à tom %%(else) més d'un cop" +#: ref-filter.c #, c-format msgid "format: %%(end) atom used without corresponding atom" msgstr "format: s'ha usat l'à tom %%(end) sense l'à tom corresponent" +#: ref-filter.c #, c-format msgid "malformed format string %s" msgstr "cadena de format mal format %s" +#: ref-filter.c #, c-format msgid "this command reject atom %%(%.*s)" msgstr "aquesta ordre rebutja l'à tom %%(%.*s)" +#: ref-filter.c #, c-format msgid "--format=%.*s cannot be used with --python, --shell, --tcl" msgstr "no es pot usar --format=%.*s amb --python, --shell, --tcl" +#: ref-filter.c msgid "failed to run 'describe'" msgstr "no s'ha pogut executar «describe»" +#: ref-filter.c #, c-format msgid "(no branch, rebasing %s)" msgstr "(sense branca, s'està fent «rebase» %s)" +#: ref-filter.c #, c-format msgid "(no branch, rebasing detached HEAD %s)" msgstr "(sense branca, s'està fent «rebase» d'un «HEAD» separat %s)" +#: ref-filter.c #, c-format msgid "(no branch, bisect started on %s)" msgstr "(sense branca, bisecció començada en %s)" +#: ref-filter.c #, c-format msgid "(HEAD detached at %s)" msgstr "(HEAD separat a %s)" +#: ref-filter.c #, c-format msgid "(HEAD detached from %s)" msgstr "(HEAD separat des de %s)" +#: ref-filter.c msgid "(no branch)" msgstr "(sense branca)" +#: ref-filter.c #, c-format msgid "missing object %s for %s" msgstr "manca l'objecte %s per a %s" +#: ref-filter.c #, c-format msgid "parse_object_buffer failed on %s for %s" msgstr "parse_object_buffer ha fallat en %s per a %s" +#: ref-filter.c #, c-format msgid "malformed object at '%s'" msgstr "objecte mal format a «%s»" +#: ref-filter.c #, c-format msgid "ignoring ref with broken name %s" msgstr "s'està ignorant la referència amb nom malmès %s" +#: ref-filter.c refs.c #, c-format msgid "ignoring broken ref %s" msgstr "s'està ignorant la referència malmesa %s" +#: ref-filter.c #, c-format msgid "format: %%(end) atom missing" msgstr "format: manca l'à tom %%(end)" +#: ref-filter.c #, c-format msgid "malformed object name %s" msgstr "nom d'objecte %s mal format" +#: ref-filter.c #, c-format msgid "option `%s' must point to a commit" msgstr "l'opció «%s» ha d'apuntar a una comissió" +#: ref-filter.h msgid "key" msgstr "clau" +#: ref-filter.h msgid "field name to sort on" msgstr "nom del camp en el qual ordenar" +#: ref-filter.h msgid "exclude refs which match pattern" msgstr "exclou refs que coincideixin amb el patró" +#: reflog.c #, c-format msgid "not a reflog: %s" -msgstr "no és un registre de referència: %s" +msgstr "no és un registre de referències: %s" +#: reflog.c #, c-format msgid "no reflog for '%s'" -msgstr "cap registre de referència per a «%s»" +msgstr "cap registre de referències per a «%s»" +#: refs.c #, c-format msgid "%s does not point to a valid object!" msgstr "%s no apunta a un objecte và lid" +#: refs.c #, c-format msgid "" "Using '%s' as the name for the initial branch. This default branch name\n" @@ -19492,231 +24969,438 @@ msgstr "" "\n" "\tgit branch -m <nom>\n" +#: refs.c #, c-format msgid "could not retrieve `%s`" msgstr "no s'ha pogut recuperar «%s»" +#: refs.c #, c-format msgid "invalid branch name: %s = %s" msgstr "nom de branca no và lida: %s = %s" +#: refs.c #, c-format msgid "ignoring dangling symref %s" -msgstr "s'està ignorant symref penjant %s" +msgstr "s'està ignorant referència simbòlica despenjada %s" +#: refs.c #, c-format msgid "log for ref %s has gap after %s" msgstr "registre per a ref %s té un buit després de %s" +#: refs.c #, c-format msgid "log for ref %s unexpectedly ended on %s" msgstr "registre per als ref %s ha acabat inesperadament a %s" +#: refs.c #, c-format msgid "log for %s is empty" msgstr "el registre per a %s és buit" +#: refs.c +msgid "refusing to force and skip creation of reflog" +msgstr "" +"s'ha rebutjat l'acció forçada i l'omissió de crear un registre de referències" + +#: refs.c #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "s'està refusant la referència amb nom malmès «%s»" +#: refs.c +#, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "s'ha rebutjat l'actualització de la pseudoreferència «%s»" + +#: refs.c #, c-format msgid "update_ref failed for ref '%s': %s" msgstr "ha fallat update_ref per a la ref «%s»: %s" +#: refs.c #, c-format msgid "multiple updates for ref '%s' not allowed" msgstr "no es permeten múltiples actualitzacions per a la referència «%s»" +#: refs.c msgid "ref updates forbidden inside quarantine environment" msgstr "no està permès actualitzar les referències en un entorn de quarantena" +#: refs.c msgid "ref updates aborted by hook" msgstr "les actualitzacions de referències s'han avortat per un lligam" +#: refs.c #, c-format msgid "'%s' exists; cannot create '%s'" msgstr "«%s» existeix; no es pot crear «%s»" +#: refs.c #, c-format msgid "cannot process '%s' and '%s' at the same time" msgstr "no es poden processar «%s» i «%s» a la vegada" +#: refs.c #, c-format msgid "could not delete reference %s: %s" msgstr "no s'ha pogut suprimir la referència %s: %s" +#: refs.c #, c-format msgid "could not delete references: %s" msgstr "no s'han pogut suprimir les referències: %s" +# 2 lÃnies OK? +#: refs.c +#, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "" +"S'ha acabat la prova no destructiva de migració de referències;\n" +"el resultat es pot trobar a «%s»\n" + +# migració OK? +#: refs.c +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "no s'ha pogut eliminar el directori temporal de migració «%s»" + +# migrar OK? +#: refs.c +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "les referències migrades es poden trobar en «%s»" + +#: refs/files-backend.c refs/reftable-backend.c +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"no puc bloquejar la referència«%s»: s'esperava una referència\n" +"simbòlica amb destinació «%s» però és una referència regular" + +#: refs/files-backend.c +#, c-format +msgid "cannot open directory %s" +msgstr "no es pot obrir el directori «%s»" + +#: refs/files-backend.c +msgid "Checking references consistency" +msgstr "S'està comprovant la consistència de les referències" + +#: refs/reftable-backend.c +#, c-format +msgid "refname is dangerous: %s" +msgstr "el nom de referència és perillós: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "" +"s'està intentant escriure la referència «%s» amb l'objecte que no existeix %s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "" +"s'està intentant escriure un objecte no de comissió %s en la branca «%s»" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"no es permeten actualitzacions múltiples de «HEAD» (inclosa una feta a " +"través del\n" +"seu referent «%s»)" + +# bloquejar → blocar +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "" +"no es pot bloquejar la referència «%s»: no s'ha pogut resoldre la referència " +"«%s»" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "no es pot bloquejar la referència «%s»: error en llegir la referència" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"no es permeten les actualitzacions múltiples per a «%s» (inclosa una a\n" +"través de la referència simbòlica «%s»" + +# bloquejar→blocar? +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "no puc bloquejar la referència «%s»: la referència ja existeix" + +# massa llarg? +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"no puc bloquejar la referència «%s»: manca la referència però s'esperava %s" + +# blocar→bloquejar? +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "no puc bloquejar la referència «%s»: és en %s però s'esperava %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "taula de referències: prepara transacció: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "taula de referències: fallada de transacció: %s" + +# stack→pila OK? +#: refs/reftable-backend.c +#, c-format +msgid "unable to compact stack: %s" +msgstr "no es pot compactar la pila: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s not found" +msgstr "no s'ha trobat el nom de referència %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "" +"el nom de referència %s és una referència simbòlica: no es permet copiar" + +#: refspec.c #, c-format msgid "invalid refspec '%s'" msgstr "refspec no và lida: «%s»" +#: remote-curl.c #, c-format msgid "invalid quoting in push-option value: '%s'" msgstr "citació no và lida en el valor de l'opció de pujada: «%s»" +# object-format no traduït perquè és part de --show-object-format +#: remote-curl.c +#, c-format +msgid "unknown value for object-format: %s" +msgstr "valor desconegut per a l'object-format: %s" + +#: remote-curl.c #, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs no và lides: és un repositori git?" +#: remote-curl.c msgid "invalid server response; expected service, got flush packet" msgstr "" "resposta del servidor no és và lida; el servei esperat, ha rebut in paquet de " "neteja" +#: remote-curl.c #, c-format msgid "invalid server response; got '%s'" msgstr "resposta del servidor no và lida; s'ha obtingut «%s»" +#: remote-curl.c #, c-format msgid "repository '%s' not found" msgstr "no s'ha trobat el repositori «%s»" +#: remote-curl.c #, c-format msgid "Authentication failed for '%s'" msgstr "S'ha produït un error en autenticar per «%s»" +#: remote-curl.c #, c-format msgid "unable to access '%s' with http.pinnedPubkey configuration: %s" msgstr "no es pot accedir a «%s» la configuració de http.pinnedPubkey :%s" +#: remote-curl.c #, c-format msgid "unable to access '%s': %s" msgstr "no s'ha pogut accedir a «%s»: %s" +#: remote-curl.c #, c-format msgid "redirecting to %s" msgstr "s'està redirigint a %s" +#: remote-curl.c msgid "shouldn't have EOF when not gentle on EOF" msgstr "no hauria de tenir EOF quan s'és lax amb els EOF" +#: remote-curl.c msgid "remote server sent unexpected response end packet" msgstr "el servidor remot ha enviat un paquet de final de resposta inesperat" +#: remote-curl.c msgid "unable to rewind rpc post data - try increasing http.postBuffer" msgstr "" "no s'han pogut rebobinar les dades de publicació rpc - proveu d'augmentar " "http.postBuffer" +#: remote-curl.c #, c-format msgid "remote-curl: bad line length character: %.4s" msgstr "remote-curl: carà cter de longitud de lÃnia erroni: %.4s" +#: remote-curl.c msgid "remote-curl: unexpected response end packet" msgstr "remote-curl: paquet final de resposta inesperat" +#: remote-curl.c #, c-format msgid "RPC failed; %s" msgstr "RPC ha fallat; %s" +#: remote-curl.c msgid "cannot handle pushes this big" msgstr "no es pot gestionar pujades tan grans" +#: remote-curl.c #, c-format msgid "cannot deflate request; zlib deflate error %d" msgstr "no es pot descomprimir la sol·licitud; error de deflate zlib %d" +#: remote-curl.c #, c-format msgid "cannot deflate request; zlib end error %d" msgstr "" "no es pot descomprimir la sol·licitud; error de finalització de zlib %d" +#: remote-curl.c #, c-format msgid "%d bytes of length header were received" -msgstr "s'han rebut %d bytes de longitud de capçalera" +msgstr "s'han rebut %d octets de longitud de capçalera" +#: remote-curl.c #, c-format msgid "%d bytes of body are still expected" -msgstr "encara s'esperen %d bytes del cos" +msgstr "encara s'esperen %d octets del cos" +#: remote-curl.c msgid "dumb http transport does not support shallow capabilities" msgstr "el transport ximple http no admet capacitats superficials" +#: remote-curl.c msgid "fetch failed." msgstr "l'obtenció ha fallat." +#: remote-curl.c msgid "cannot fetch by sha1 over smart http" msgstr "no s'ha pogut obtenir per sha1 a través de l'http intel·ligent" +#: remote-curl.c #, c-format msgid "protocol error: expected sha/ref, got '%s'" msgstr "error de protocol: s'esperava sha/ref, s'ha obtingut «%s»" +#: remote-curl.c #, c-format msgid "http transport does not support %s" msgstr "El transport http no admet %s" +#: remote-curl.c msgid "protocol error: expected '<url> <path>', missing space" msgstr "" "s'ha produït un error de protocol: s'esperava «<url> <camÃ>», falta espai" +#: remote-curl.c #, c-format msgid "failed to download file at URL '%s'" msgstr "no s'ha pogut baixar el fitxer a l'URL «%s»" +#: remote-curl.c msgid "git-http-push failed" msgstr "git-http-push ha fallat" +#: remote-curl.c msgid "remote-curl: usage: git remote-curl <remote> [<url>]" -msgstr "remote-curl: ús: git remote-curl <remote> [<url>]" +msgstr "remote-curl: ús: git remote-curl <remot> [<url>]" +#: remote-curl.c msgid "remote-curl: error reading command stream from git" msgstr "remote-curl: error en llegir el flux d'ordres del git" +#: remote-curl.c msgid "remote-curl: fetch attempted without a local repo" msgstr "remote-curl: s'ha intentat l'obtenció sense un repositori local" +#: remote-curl.c #, c-format msgid "remote-curl: unknown command '%s' from git" msgstr "remote-curl: ordre «%s» desconeguda del git" +#: remote.c #, c-format msgid "config remote shorthand cannot begin with '/': %s" msgstr "" "l'abreviatura del fitxer de configuració remot no pot començar amb «/»: %s" +#: remote.c msgid "more than one receivepack given, using the first" msgstr "més d'un paquet de recepció donat, usant el primer" +#: remote.c msgid "more than one uploadpack given, using the first" msgstr "més d'un paquet de cà rrega donat, usant el primer" +#: remote.c #, c-format msgid "unrecognized value transfer.credentialsInUrl: '%s'" msgstr "valor no conegut per a transfer.credentialsInUrl: «%s»" +#: remote.c #, c-format msgid "URL '%s' uses plaintext credentials" msgstr "L'URL «%s» utilitza credencials en text pla" +#: remote.c #, c-format msgid "Cannot fetch both %s and %s to %s" msgstr "No es poden obtenir ambdós %s i %s a %s" +#: remote.c #, c-format msgid "%s usually tracks %s, not %s" msgstr "%s generalment segueix %s, no %s" +#: remote.c #, c-format msgid "%s tracks both %s and %s" msgstr "%s segueix ambdós %s i %s" +#: remote.c #, c-format msgid "key '%s' of pattern had no '*'" msgstr "la clau «%s» del patró no té «*»" +#: remote.c #, c-format msgid "value '%s' of pattern has no '*'" msgstr "el valor «%s» del patró no té «*»" +#: remote.c #, c-format msgid "src refspec %s does not match any" msgstr "l'especificació de referència font %s no coincideix amb cap referència" +#: remote.c #, c-format msgid "src refspec %s matches more than one" msgstr "" @@ -19726,6 +25410,7 @@ msgstr "" #. <remote> <src>:<dst>" push, and "being pushed ('%s')" is #. the <src>. #. +#: remote.c #, c-format msgid "" "The destination you provided is not a full refname (i.e.,\n" @@ -19748,6 +25433,7 @@ msgstr "" "\n" "Res d'això ha funcionat. Cal que proporcioneu una referència completa." +#: remote.c #, c-format msgid "" "The <src> part of the refspec is a commit object.\n" @@ -19759,6 +25445,7 @@ msgstr "" "Voleu crear una branca nova empenyent a\n" "«%s:refs/heads/%s»?" +#: remote.c #, c-format msgid "" "The <src> part of the refspec is a tag object.\n" @@ -19768,6 +25455,7 @@ msgstr "" "La part <src> de l'especificació de la referència és un objecte d'etiqueta.\n" "Voleu crear una etiqueta pujant-la a «%s:refs/tags/%s»?" +#: remote.c #, c-format msgid "" "The <src> part of the refspec is a tree object.\n" @@ -19777,6 +25465,7 @@ msgstr "" "La part <src> de l'especificació de la referència és un objecte d'arbre.\n" "Voleu crear una etiqueta pujant-la a «%s:refs/tags/%s»?" +#: remote.c #, c-format msgid "" "The <src> part of the refspec is a blob object.\n" @@ -19787,93 +25476,116 @@ msgstr "" "Voleu posar una etiqueta al blob nou mitjançant la pujada a\n" "?«%s:refs/tags/%s»?" +#: remote.c #, c-format msgid "%s cannot be resolved to branch" msgstr "«%s» no es pot resoldre a una branca" +#: remote.c #, c-format msgid "unable to delete '%s': remote ref does not exist" msgstr "no s'ha pogut suprimir «%s»: la referència remota no existeix" +#: remote.c #, c-format msgid "dst refspec %s matches more than one" msgstr "" "l'especificació de la referència dst %s coincideixen amb més d'una referència" +#: remote.c #, c-format msgid "dst ref %s receives from more than one src" msgstr "l'especificació de la referència dst %s rep més d'una referència src" +#: remote.c msgid "HEAD does not point to a branch" msgstr "HEAD no assenyala cap branca" +#: remote.c #, c-format msgid "no such branch: '%s'" msgstr "no existeix la branca: «%s»" +#: remote.c #, c-format msgid "no upstream configured for branch '%s'" msgstr "cap font configurada per a la branca «%s»" +#: remote.c #, c-format msgid "upstream branch '%s' not stored as a remote-tracking branch" msgstr "la branca font «%s» no s'emmagatzema com a branca amb seguiment remot" +#: remote.c #, c-format msgid "push destination '%s' on remote '%s' has no local tracking branch" msgstr "" "el destà de pujada «%s» en el remot «%s» no té cap branca amb seguiment remot" +#: remote.c #, c-format msgid "branch '%s' has no remote for pushing" msgstr "la branca «%s» no té cap remot al qual pujar" +#: remote.c #, c-format msgid "push refspecs for '%s' do not include '%s'" msgstr "les especificacions de referència de pujada «%s» no inclouen «%s»" +#: remote.c msgid "push has no destination (push.default is 'nothing')" msgstr "push no té destà (push.default és «nothing»)" +#: remote.c msgid "cannot resolve 'simple' push to a single destination" msgstr "no es pot resoldre una pujada «simple» a un sol destÃ" +#: remote.c #, c-format msgid "couldn't find remote ref %s" msgstr "no s'ha pogut trobar la referència remota %s" +#: remote.c #, c-format msgid "* Ignoring funny ref '%s' locally" msgstr "* S'estan ignorant les referències «%s» localment" +#: remote.c #, c-format msgid "Your branch is based on '%s', but the upstream is gone.\n" msgstr "La vostra branca està basada en «%s», però la font no hi és.\n" +#: remote.c msgid " (use \"git branch --unset-upstream\" to fixup)\n" msgstr " (useu «git branch --unset-upstream» per a arreglar-ho)\n" +#: remote.c #, c-format msgid "Your branch is up to date with '%s'.\n" msgstr "La vostra branca està al dia amb «%s».\n" +#: remote.c #, c-format msgid "Your branch and '%s' refer to different commits.\n" -msgstr "La vostra branca i «%s» es refereixen a diferents comissions.\n" +msgstr "La vostra branca i «%s» es refereixen a comissions.\n" +#: remote.c #, c-format msgid " (use \"%s\" for details)\n" msgstr " (useu «%s» per a detalls)\n" +#: remote.c #, c-format msgid "Your branch is ahead of '%s' by %d commit.\n" msgid_plural "Your branch is ahead of '%s' by %d commits.\n" msgstr[0] "La vostra branca està %2$d comissió per davant de «%1$s».\n" msgstr[1] "La vostra branca està %2$d comissions per davant de «%1$s».\n" +#: remote.c msgid " (use \"git push\" to publish your local commits)\n" msgstr " (useu «git push» per a publicar les vostres comissions locals)\n" +#: remote.c #, c-format msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" msgid_plural "" @@ -19885,9 +25597,11 @@ msgstr[1] "" "La vostra branca està %2$d comissions per darrere de «%1$s», i pot avançar-" "se rà pidament.\n" +#: remote.c msgid " (use \"git pull\" to update your local branch)\n" msgstr " (useu «git pull» per a actualitzar la vostra branca local)\n" +#: remote.c #, c-format msgid "" "Your branch and '%s' have diverged,\n" @@ -19902,285 +25616,387 @@ msgstr[1] "" "La vostra branca i «%s» han divergit,\n" "i tenen %d i %d comissions distintes cada una, respectivament.\n" +#: remote.c msgid "" " (use \"git pull\" if you want to integrate the remote branch with yours)\n" msgstr "" " (utilitzeu «git pull» si voleu integrar la branca remota amb la vostra)\n" +#: remote.c #, c-format msgid "cannot parse expected object name '%s'" msgstr "no es pot analitzar el nom de l'objecte esperat «%s»" +#: remote.c #, c-format msgid "cannot strip one component off url '%s'" msgstr "no es pot despullar un component de l'url «%s»" +#: replace-object.c #, c-format msgid "bad replace ref name: %s" msgstr "nom de la referència reemplaçada incorrecte: %s" +#: replace-object.c #, c-format msgid "duplicate replace ref: %s" msgstr "duplica les referències reemplaçades: %s" +#: replace-object.c #, c-format msgid "replace depth too high for object %s" msgstr "la profunditat de reemplaçament és massa alta per l'objecte %s" +#: rerere.c msgid "corrupt MERGE_RR" msgstr "MERGE_RR corrupte" +#: rerere.c msgid "unable to write rerere record" msgstr "no s'ha pogut escriure el registre «rerere»" +#: rerere.c #, c-format msgid "there were errors while writing '%s' (%s)" msgstr "s'han produït errors en escriure «%s» (%s)" +#: rerere.c #, c-format msgid "could not parse conflict hunks in '%s'" msgstr "no s'han pogut analitzar els pedaços en conflicte a «%s»" +#: rerere.c #, c-format msgid "failed utime() on '%s'" msgstr "s'ha produït un error en fer «failed utime()» a «%s»" +#: rerere.c #, c-format msgid "writing '%s' failed" msgstr "s'ha produït un error en escriure «%s»" +#: rerere.c #, c-format msgid "Staged '%s' using previous resolution." msgstr "«Staged» «%s» utilitzant una resolució anterior." +#: rerere.c #, c-format msgid "Recorded resolution for '%s'." msgstr "Es recorda la resolució per a «%s»." +#: rerere.c #, c-format msgid "Resolved '%s' using previous resolution." msgstr "S'ha resolt «%s» usant una resolució anterior." +#: rerere.c #, c-format msgid "cannot unlink stray '%s'" msgstr "no es pot desenllaçar «%s» (extraviat)" +#: rerere.c #, c-format msgid "Recorded preimage for '%s'" msgstr "Imatge prèvia registrada per a «%s»" +#: rerere.c #, c-format msgid "failed to update conflicted state in '%s'" msgstr "ha fallat en actualitzar l'estat en conflicte a «%s»" +#: rerere.c #, c-format msgid "no remembered resolution for '%s'" msgstr "no hi ha cap resolució recordada per a «%s»" +#: rerere.c #, c-format msgid "Updated preimage for '%s'" msgstr "Imatge prèvia actualitzada per a «%s»" +#: rerere.c #, c-format msgid "Forgot resolution for '%s'\n" msgstr "S'ha oblidat la resolució per a «%s»\n" +#: rerere.c msgid "unable to open rr-cache directory" msgstr "no s'ha pogut obrir el directori rr-cache" +#: rerere.h msgid "update the index with reused conflict resolution if possible" msgstr "" "actualitza l'Ãndex amb la resolució de conflictes reusada si és possible" +#: reset.c msgid "could not determine HEAD revision" msgstr "no s'ha pogut determinar la revisió de HEAD" +#: reset.c sequencer.c #, c-format msgid "failed to find tree of %s" msgstr "s'ha produït un error en cercar l'arbre de %s" +#: revision.c #, c-format msgid "unsupported section for hidden refs: %s" msgstr "secció d'Ãndex no compatible per a les referències ocultes: %s" +#: revision.c msgid "--exclude-hidden= passed more than once" msgstr "--exclude-hidden= passat més d'una vegada" +#: revision.c #, c-format msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo indica «%s» que manquen" +#: revision.c #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "no s'ha pogut obtenir la comissió per a l'argument d'ancestry-path %s" +msgid "%s exists but is a symbolic ref" +msgstr "%s existeix però és una referència simbòlica" +#: revision.c +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge requereix una de les pseudoreferències MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD o REBASE_HEAD" + +#: revision.c +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "" +"no s'ha pogut obtenir una comissió per a l'argument %s d'--ancestry-path" + +#: revision.c msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<packfile> ja no s'admet" +#: revision.c #, c-format msgid "invalid option '%s' in --stdin mode" msgstr "opció no và lida: «%s» en mode --stdin" +#: revision.c msgid "your current branch appears to be broken" msgstr "la vostra branca actual sembla malmesa" +#: revision.c #, c-format msgid "your current branch '%s' does not have any commits yet" msgstr "la branca actual «%s» encara no té cap comissió" +#: revision.c msgid "object filtering requires --objects" msgstr "el filtratge d'objectes requereix --objects" +#: revision.c msgid "-L does not yet support diff formats besides -p and -s" msgstr "-L no és encara compatible amb formats que no siguin «-p» o «-s»" +#: run-command.c #, c-format msgid "cannot create async thread: %s" msgstr "no s'ha pogut crear fil «async»: %s" +#: scalar.c worktree.c #, c-format msgid "'%s' does not exist" msgstr "«%s» no existeix" +#: scalar.c #, c-format msgid "could not switch to '%s'" msgstr "no s'ha pogut commutar a «%s»" +#: scalar.c msgid "need a working directory" msgstr "cal un directori de treball" +#: scalar.c msgid "Scalar enlistments require a worktree" msgstr "Els allistaments escalars requereixen un arbre de treball" +#: scalar.c #, c-format msgid "could not configure %s=%s" msgstr "no s'ha pogut configurar %s=%s" +#: scalar.c msgid "could not configure log.excludeDecoration" msgstr "no s'ha pogut configurar log.excludeDecoration" +#: scalar.c msgid "could not add enlistment" msgstr "no s'ha afegit a l'allistament" +#: scalar.c msgid "could not set recommended config" msgstr "no s'ha pogut establir la configuració recomanada" +#: scalar.c msgid "could not turn on maintenance" msgstr "no s'ha pogut activar el manteniment" +#: scalar.c msgid "could not start the FSMonitor daemon" msgstr "no s'ha pogut iniciar el dimoni del fsmonitor" +#: scalar.c msgid "could not turn off maintenance" msgstr "no s'ha pogut desactivar el manteniment" +#: scalar.c msgid "could not remove enlistment" msgstr "no s'ha pogut eliminar l'allistament" +#: scalar.c #, c-format msgid "remote HEAD is not a branch: '%.*s'" msgstr "la HEAD remota no és una branca: «%.*s»" +#: scalar.c msgid "failed to get default branch name from remote; using local default" msgstr "" "no s'ha pogut obtenir el nom de la branca per defecte del remot; s'usa ela " "predeterminada localment" +#: scalar.c msgid "failed to get default branch name" msgstr "s'ha produït un error en obtenir el nom de branca predeterminada" +#: scalar.c msgid "failed to unregister repository" msgstr "s'ha produït un error en desregistrar el repositori" +#: scalar.c msgid "failed to stop the FSMonitor daemon" msgstr "no s'ha pogut aturar el dimoni del FSMonitor" +#: scalar.c msgid "failed to delete enlistment directory" msgstr "s'ha produït un error en suprimir l'allistament del directori" +#: scalar.c msgid "branch to checkout after clone" msgstr "branca a agafar després de clonar" +#: scalar.c msgid "when cloning, create full working directory" msgstr "quan es clona, crear un directori de treball complet" +#: scalar.c msgid "only download metadata for the branch that will be checked out" msgstr "només baixa les metadades per a la branca que s'agafarà " +#: scalar.c msgid "create repository within 'src' directory" msgstr "crea un repositori dins del directori «src»" +#: scalar.c +msgid "specify if tags should be fetched during clone" +msgstr "especifica si les etiquetes s'han d'obtenir durant el clon" + +# Deixem <enlistment> sense traduir de moment +#: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" -"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"scalar clone [--single-branch] [--branch <branca-principal>] [--full-clone]\n" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +#: scalar.c #, c-format msgid "cannot deduce worktree name from '%s'" msgstr "no es pot deduir el nom de l'arbre de treball de «%s»" +#: scalar.c #, c-format msgid "directory '%s' exists already" msgstr "el directori «%s» ja existeix" +#: scalar.c #, c-format msgid "failed to get default branch for '%s'" msgstr "s'ha produït un error en obtenir la branca per defecte per a «%s»" +#: scalar.c #, c-format msgid "could not configure remote in '%s'" msgstr "no s'ha pogut configurar el remot a «%s»" +#: scalar.c +#, c-format +msgid "could not disable tags in '%s'" +msgstr "no s'han pogut inhabilitar les etiquetes en «%s»" + +#: scalar.c #, c-format msgid "could not configure '%s'" msgstr "no s'ha pogut configurar «%s»" +#: scalar.c msgid "partial clone failed; attempting full clone" msgstr "ha fallat la clonació parcial; s'està intentant la clonació completa" +#: scalar.c msgid "could not configure for full clone" msgstr "no s'ha pogut configurar per a una clonació completa" +#: scalar.c msgid "scalar diagnose [<enlistment>]" msgstr "scalar diagnose [<enlistment>]" +#: scalar.c msgid "`scalar list` does not take arguments" msgstr "«scalar list» no accepta arguments" +#: scalar.c msgid "scalar register [<enlistment>]" msgstr "scalar register [<enlistment>]" +#: scalar.c msgid "reconfigure all registered enlistments" msgstr "reconfigura tots els allistaments registrats" +#: scalar.c msgid "scalar reconfigure [--all | <enlistment>]" msgstr "scalar reconfigure [--all | <enlistment>]" +#: scalar.c msgid "--all or <enlistment>, but not both" msgstr "--all o <enlistment>, però no ambdós" +#: scalar.c #, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "no s'ha pogut suprimir el scalar.repo «%s» estancat" +#: scalar.c #, c-format msgid "removed stale scalar.repo '%s'" msgstr "s'ha eliminat l'scalar.repo estancat «%s»" +#: scalar.c #, c-format msgid "repository at '%s' has different owner" msgstr "el dipòsit a «%s» té un propietari diferent" +#: scalar.c #, c-format msgid "repository at '%s' has a format issue" msgstr "el dipòsit a «%s» té un problema de format" +#: scalar.c #, c-format msgid "repository not found in '%s'" msgstr "no s'ha trobat el dipòsit a «%s»" +#: scalar.c #, c-format msgid "" "to unregister this repository from Scalar, run\n" @@ -20189,6 +26005,7 @@ msgstr "" "per a desregistrar aquest dipòsit de l'escalar, executeu\n" "\tgit config --global --unset --fixed-value scalar.repo «%s»" +#: scalar.c msgid "" "scalar run <task> [<enlistment>]\n" "Tasks:\n" @@ -20196,77 +26013,97 @@ msgstr "" "scalar run <task> {<enlistment>]\n" "Tasques:\n" +#: scalar.c #, c-format msgid "no such task: '%s'" msgstr "no existeix la tasca: «%s»" +#: scalar.c msgid "scalar unregister [<enlistment>]" msgstr "scalar unregister [<enlistment>]" +#: scalar.c msgid "scalar delete <enlistment>" msgstr "supressió de l'escalar <enlistment>" +#: scalar.c msgid "refusing to delete current working directory" msgstr "s'ha rebutjat suprimir el directori de treball actual" +#: scalar.c msgid "include Git version" msgstr "inclou la versió del Git" +#: scalar.c msgid "include Git's build options" msgstr "inclou les opcions de construcció del Git" +#: scalar.c msgid "scalar verbose [-v | --verbose] [--build-options]" msgstr "scalar verbose [-v | --verbose] [--build-options]" +#: scalar.c msgid "-C requires a <directory>" -msgstr "-C requereix un <directory>" +msgstr "-C requereix un <directori>" +#: scalar.c #, c-format msgid "could not change to '%s'" msgstr "no s'ha pogut canviar a «%s»" +#: scalar.c msgid "-c requires a <key>=<value> argument" -msgstr "-c requereix un argument <key>=<value>" +msgstr "-c requereix un argument <clau>=<valor>" +#: scalar.c msgid "" "scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n" "\n" "Commands:\n" msgstr "" -"scalar [-C <directory>] [-c <key>=<value>] <command> [<opcions>]\n" +"scalar [-C <directori>] [-c <clau>=<valor>] <ordre> [<opcions>]\n" "\n" "Ordres:\n" +#: send-pack.c msgid "unexpected flush packet while reading remote unpack status" msgstr "" "paquet de buidatge no esperat quan estava llegint l'estat del " "desempaquetament remot" +#: send-pack.c #, c-format msgid "unable to parse remote unpack status: %s" msgstr "no s'ha pogut analitzar l'estat del desempaquetament remot: %s" +#: send-pack.c #, c-format msgid "remote unpack failed: %s" msgstr "s'ha produït un error en el desempaquetament remot: %s" +#: send-pack.c msgid "failed to sign the push certificate" msgstr "s'ha produït un error en signar el certificat de pujada" +#: send-pack.c msgid "send-pack: unable to fork off fetch subprocess" msgstr "send-pack: no es pot bifurcar obtenint un subprocés" +#: send-pack.c msgid "push negotiation failed; proceeding anyway with push" msgstr "" "ha fallat la negociació de la pujada; s'està procedint igualment amb " "l'empenta" +#: send-pack.c msgid "the receiving end does not support this repository's hash algorithm" msgstr "el receptor de destà no admet l'algorisme de resum del repositori" +#: send-pack.c msgid "the receiving end does not support --signed push" msgstr "el destà receptor no admet pujar --signed" +#: send-pack.c msgid "" "not sending a push certificate since the receiving end does not support --" "signed push" @@ -20274,33 +26111,58 @@ msgstr "" "no s'està enviant una certificació de pujada perquè el destà receptor no " "admet pujar --signed" +#: send-pack.c msgid "the receiving end does not support --atomic push" msgstr "el destà receptor no admet pujar --atomic" +#: send-pack.c msgid "the receiving end does not support push options" msgstr "el receptor al destà no admet opcions de pujada" +#: sequencer.c #, c-format msgid "invalid commit message cleanup mode '%s'" msgstr "mode de neteja «%s» no và lid en la comissió del missatge" +#: sequencer.c #, c-format msgid "could not delete '%s'" msgstr "no s'ha pogut suprimir «%s»" +#: sequencer.c msgid "revert" msgstr "revertir" +#: sequencer.c msgid "cherry-pick" msgstr "cherry-pick" +#: sequencer.c msgid "rebase" msgstr "rebase" +#: sequencer.c #, c-format msgid "unknown action: %d" msgstr "acció desconeguda: %d" +#: sequencer.c +msgid "" +"Resolve all conflicts manually, mark them as resolved with\n" +"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n" +"You can instead skip this commit: run \"git rebase --skip\".\n" +"To abort and get back to the state before \"git rebase\", run \"git rebase --" +"abort\"." +msgstr "" +"Resoleu tots els conflictes manualment, marqueu-los com a resolts amb\n" +"«git add/rm <fitxers_amb_conflicte>», llavors executeu «git rebase --" +"continue».\n" +"Alternativament podeu ometre aquesta comissió: executeu «git rebase --" +"skip».\n" +"Per a avortar i tornar a l'estat anterior abans de l'ordre «git rebase», " +"executeu «git rebase --abort»." + +#: sequencer.c msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" @@ -20308,6 +26170,7 @@ msgstr "" "després de resoldre els conflictes, marqueu els camins\n" "corregits amb «git add <camins>» o «git rm <camins>»" +#: sequencer.c msgid "" "After resolving the conflicts, mark them with\n" "\"git add/rm <pathspec>\", then run\n" @@ -20323,6 +26186,7 @@ msgstr "" "Per a interrompre i tornar a l'estat anterior abans de «git cherry-pick»,\n" "executeu «git cherry-pick --abort»." +#: sequencer.c msgid "" "After resolving the conflicts, mark them with\n" "\"git add/rm <pathspec>\", then run\n" @@ -20338,68 +26202,86 @@ msgstr "" "Per a interrompre i tornar a l'estat anterior abans de «git revert»,\n" "executeu «git revert --abort»." +#: sequencer.c #, c-format msgid "could not lock '%s'" msgstr "no s'ha pogut bloquejar «%s»" +#: sequencer.c #, c-format msgid "could not write eol to '%s'" msgstr "no s'ha pogut escriure el terminador de lÃnia a «%s»" +#: sequencer.c #, c-format msgid "failed to finalize '%s'" msgstr "s'ha produït un error en finalitzar «%s»" +#: sequencer.c #, c-format msgid "your local changes would be overwritten by %s." msgstr "els vostres canvis locals se sobreescriurien per %s." +#: sequencer.c msgid "commit your changes or stash them to proceed." msgstr "cometeu els vostres canvis o feu un «stash» per a procedir." #. TRANSLATORS: %s will be "revert", "cherry-pick" or #. "rebase". #. +#: sequencer.c #, c-format msgid "%s: Unable to write new index file" msgstr "%s: No s'ha pogut escriure un fitxer d'Ãndex nou" +#: sequencer.c msgid "unable to update cache tree" msgstr "no s'ha pogut actualitzar l'arbre cau" +#: sequencer.c msgid "could not resolve HEAD commit" msgstr "no s'ha pogut resoldre la comissió HEAD" +#: sequencer.c #, c-format msgid "no key present in '%.*s'" msgstr "no hi ha una clau a «%.*s»" +#: sequencer.c #, c-format msgid "unable to dequote value of '%s'" msgstr "no s'han pogut treure les cometes del valor de «%s»" +#: sequencer.c msgid "'GIT_AUTHOR_NAME' already given" msgstr "Ja s'ha donat «GIT_AUTHOR_NAME»" +#: sequencer.c msgid "'GIT_AUTHOR_EMAIL' already given" msgstr "Ja s'ha donat «GIT_AUTHOR_EMAIL»" +#: sequencer.c msgid "'GIT_AUTHOR_DATE' already given" msgstr "Ja s'ha donat «GIT_AUTHOR_DATE»" +#: sequencer.c #, c-format msgid "unknown variable '%s'" msgstr "variable «%s» desconeguda" +#: sequencer.c msgid "missing 'GIT_AUTHOR_NAME'" msgstr "falta «GIT_AUTHOR_NAME»" +#: sequencer.c msgid "missing 'GIT_AUTHOR_EMAIL'" msgstr "falta «GIT_AUTHOR_EMAIL»" +#: sequencer.c msgid "missing 'GIT_AUTHOR_DATE'" msgstr "falta «GIT_AUTHOR_DATE»" +#: sequencer.c #, c-format msgid "" "you have staged changes in your working tree\n" @@ -20429,9 +26311,11 @@ msgstr "" "\n" " git rebase --continue\n" +#: sequencer.c msgid "'prepare-commit-msg' hook failed" msgstr "el lligam «prepare-commit-msg» ha fallat" +#: sequencer.c msgid "" "Your name and email address were configured automatically based\n" "on your username and hostname. Please check that they are accurate.\n" @@ -20458,6 +26342,7 @@ msgstr "" "\n" " git commit --amend --reset-author\n" +#: sequencer.c msgid "" "Your name and email address were configured automatically based\n" "on your username and hostname. Please check that they are accurate.\n" @@ -20483,259 +26368,369 @@ msgstr "" "\n" " git commit --amend --reset-author\n" +#: sequencer.c msgid "couldn't look up newly created commit" msgstr "no s'ha pogut trobar la comissió novament creada" +#: sequencer.c msgid "could not parse newly created commit" msgstr "no s'ha pogut analitzar la comissió novament creada" +#: sequencer.c msgid "unable to resolve HEAD after creating commit" msgstr "no s'ha pogut resoldre HEAD després de crear la comissió" +#: sequencer.c msgid "detached HEAD" msgstr "HEAD separat" +#: sequencer.c msgid " (root-commit)" msgstr " (comissió arrel)" +#: sequencer.c msgid "could not parse HEAD" msgstr "no s'ha pogut analitzar HEAD" +#: sequencer.c #, c-format msgid "HEAD %s is not a commit!" msgstr "HEAD %s no és una comissió!" +#: sequencer.c msgid "unable to parse commit author" msgstr "no s'ha pogut analitzar l'autor de la comissió" +#: sequencer.c #, c-format msgid "unable to read commit message from '%s'" msgstr "no s'ha pogut llegir el missatge de comissió des de «%s»" +#: sequencer.c #, c-format msgid "invalid author identity '%s'" msgstr "identitat d'autor no và lida: «%s»" +#: sequencer.c msgid "corrupt author: missing date information" msgstr "autor malmès: falta la informació de la data" +#: sequencer.c #, c-format msgid "could not update %s" msgstr "no s'ha pogut actualitzar %s" -#, c-format -msgid "could not parse commit %s" -msgstr "no s'ha pogut analitzar la comissió %s" - +#: sequencer.c #, c-format msgid "could not parse parent commit %s" msgstr "no s'ha pogut analitzar la comissió pare %s" +#: sequencer.c #, c-format msgid "unknown command: %d" msgstr "ordre desconeguda: %d" +#: sequencer.c msgid "This is the 1st commit message:" msgstr "Aquest és el missatge de la 1a comissió:" +#: sequencer.c #, c-format msgid "This is the commit message #%d:" msgstr "Aquest és el missatge de la #%d comissió:" +#: sequencer.c msgid "The 1st commit message will be skipped:" msgstr "El missatge de la primera comissió s'ometrà :" +#: sequencer.c #, c-format msgid "The commit message #%d will be skipped:" msgstr "El missatge de la comissió núm. #%d s'ometrà :" +#: sequencer.c #, c-format msgid "This is a combination of %d commits." msgstr "Això és una combinació de %d comissions." +#: sequencer.c #, c-format msgid "cannot write '%s'" msgstr "no es pot escriure «%s»" +#: sequencer.c msgid "need a HEAD to fixup" msgstr "cal un HEAD per a reparar-ho" +#: sequencer.c msgid "could not read HEAD" msgstr "no s'ha pogut llegir HEAD" +#: sequencer.c msgid "could not read HEAD's commit message" msgstr "no s'ha pogut llegir el missatge de comissió de HEAD" +#: sequencer.c #, c-format msgid "could not read commit message of %s" msgstr "no s'ha pogut llegir el missatge de comissió: %s" +#: sequencer.c msgid "your index file is unmerged." msgstr "el vostre fitxer d'Ãndex està sense fusionar." +#: sequencer.c msgid "cannot fixup root commit" msgstr "no es pot arreglar la comissió arrel" +#: sequencer.c #, c-format msgid "commit %s is a merge but no -m option was given." msgstr "la comissió %s és una fusió però no s'ha donat cap opció -m." +#: sequencer.c #, c-format msgid "commit %s does not have parent %d" msgstr "la comissió %s no té pare %d" +#: sequencer.c #, c-format msgid "cannot get commit message for %s" msgstr "no es pot obtenir el missatge de comissió de %s" #. TRANSLATORS: The first %s will be a "todo" command like #. "revert" or "pick", the second %s a SHA1. +#: sequencer.c #, c-format msgid "%s: cannot parse parent commit %s" msgstr "%s: no es pot analitzar la comissió pare %s" +#: sequencer.c #, c-format msgid "could not revert %s... %s" msgstr "no s'ha pogut revertir %s... %s" +#: sequencer.c #, c-format msgid "could not apply %s... %s" msgstr "no s'ha pogut aplicar %s... %s" +#: sequencer.c #, c-format msgid "dropping %s %s -- patch contents already upstream\n" msgstr "descartant %s %s -- el contingut del pedaç ja està a la font\n" +#: sequencer.c #, c-format msgid "git %s: failed to read the index" msgstr "git %s: s'ha produït un error en llegir l'Ãndex" +#: sequencer.c #, c-format msgid "git %s: failed to refresh the index" msgstr "git %s: s'ha produït un error en actualitzar l'Ãndex" +#: sequencer.c #, c-format msgid "'%s' is not a valid label" msgstr "«%s» no és una etiqueta và lida" +#: sequencer.c #, c-format msgid "'%s' is not a valid refname" msgstr "«%s» no és un nom de referència và lid" +#: sequencer.c #, c-format msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s" msgstr "" "«update-ref» requereix un refname plenament qualificat, p. ex. refs/heads/%s" +#: sequencer.c #, c-format -msgid "invalid command '%.*s'" -msgstr "ordre no và lida «%.*s»" +msgid "'%s' does not accept merge commits" +msgstr "%s no accepta comissions de fusió" +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"«pick» no accepta una comissió de fusió. Si volÃeu\n" +"reproduir la fusió, utilitzeu «merge -C» en la comissió." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"«reword» no accepta una comissió de fusió. Si volÃeu\n" +"reproduir la fusió i fer «reword» del missatge de comissió,\n" +"utilitzeu «merge -c» en la comissió" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +#: sequencer.c +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"«edit» no accepta una comissió de fusió. Si volÃeu\n" +"reproduir la fusió, utilitzeu «merge -C» en la comissió\n" +" i després «break» per a recuperar el control perquè pugueu\n" +"feu «git commit --amend && git rebase --continue»." + +#: sequencer.c +msgid "cannot squash merge commit into another commit" +msgstr "no es pot fer «squash» d'una comissió de fusió en una altra comissió" + +#: sequencer.c #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s no accepta arguments: «%s»" +msgid "invalid command '%.*s'" +msgstr "ordre no và lida «%.*s»" +#: sequencer.c #, c-format msgid "missing arguments for %s" msgstr "falten els arguments per a %s" +#: sequencer.c #, c-format msgid "could not parse '%s'" msgstr "no s'ha pogut analitzar «%s»" +#: sequencer.c #, c-format msgid "invalid line %d: %.*s" msgstr "lÃnia no và lida %d: %.*s" +#: sequencer.c #, c-format msgid "cannot '%s' without a previous commit" msgstr "no es pot «%s» sense una comissió prèvia" +#: sequencer.c msgid "cancelling a cherry picking in progress" msgstr "s'està cancel·lant un «cherry pick» en curs" +#: sequencer.c msgid "cancelling a revert in progress" msgstr "s'està cancel·lant la reversió en curs" +#: sequencer.c msgid "please fix this using 'git rebase --edit-todo'." msgstr "corregiu-ho usant «git rebase --edit-todo»." +#: sequencer.c #, c-format msgid "unusable instruction sheet: '%s'" msgstr "full d'instruccions inusable: «%s»" +#: sequencer.c msgid "no commits parsed." msgstr "no s'ha analitzat cap comissió." +#: sequencer.c msgid "cannot cherry-pick during a revert." msgstr "no es pot fer «cherry pick» durant una reversió." +#: sequencer.c msgid "cannot revert during a cherry-pick." msgstr "no es pot revertir durant un «cherry pick»." +#: sequencer.c msgid "unusable squash-onto" msgstr "«squash-onto» no usable" +#: sequencer.c #, c-format msgid "malformed options sheet: '%s'" msgstr "full d'opcions mal format: «%s»" +#: sequencer.c msgid "empty commit set passed" msgstr "conjunt de comissions buit passat" +#: sequencer.c msgid "revert is already in progress" msgstr "una reversió ja està en curs" +#: sequencer.c #, c-format msgid "try \"git revert (--continue | %s--abort | --quit)\"" msgstr "intenteu «git revert (--continue | %s--abort | --quit)»" +#: sequencer.c msgid "cherry-pick is already in progress" msgstr "un «cherry pick» ja està en curs" +#: sequencer.c #, c-format msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\"" msgstr "intenteu «git cherry-pick (--continue | %s--abort | --quit)»" +#: sequencer.c #, c-format msgid "could not create sequencer directory '%s'" msgstr "no s'ha pogut crear el directori de seqüenciador «%s»" +#: sequencer.c msgid "no cherry-pick or revert in progress" msgstr "ni hi ha cap «cherry pick» ni cap reversió en curs" +#: sequencer.c msgid "cannot resolve HEAD" msgstr "no es pot resoldre HEAD" +#: sequencer.c msgid "cannot abort from a branch yet to be born" msgstr "no es pot avortar des d'una branca que encara ha de nà ixer" +#: sequencer.c #, c-format msgid "cannot read '%s': %s" msgstr "no es pot llegir «%s»: %s" +#: sequencer.c msgid "unexpected end of file" msgstr "final de fitxer inesperat" +#: sequencer.c #, c-format msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" msgstr "el fitxer HEAD emmagatzemat abans de fer «cherry pick» «%s» és malmès" +#: sequencer.c msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!" -msgstr "Sembla que heu mogut HEAD sense rebobinar, comproveu-ho HEAD" +msgstr "Sembla que heu mogut HEAD. No es fa el rebobinat, comproveu-ho HEAD" +#: sequencer.c msgid "no revert in progress" msgstr "no hi ha cap reversió en curs" +#: sequencer.c msgid "no cherry-pick in progress" msgstr "ni hi ha cap «cherry pick» en curs" +#: sequencer.c msgid "failed to skip the commit" msgstr "s'ha produït un error en ometre la comissió" +#: sequencer.c msgid "there is nothing to skip" msgstr "no hi ha res a ometre" +#: sequencer.c #, c-format msgid "" "have you committed already?\n" @@ -20744,13 +26739,15 @@ msgstr "" "heu fet ja una comissió?\n" "proveu «git %s --continue»" +#: sequencer.c msgid "cannot read HEAD" msgstr "no es pot llegir HEAD" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "no s'ha pogut copiar «%s» a «%s»" +#: sequencer.c +msgid "could not write commit message file" +msgstr "no s'ha pogut escriure el fitxer de missatge de comissió" +#: sequencer.c #, c-format msgid "" "You can amend the commit now, with\n" @@ -20769,18 +26766,22 @@ msgstr "" "\n" " git rebase --continue\n" +#: sequencer.c #, c-format msgid "Could not apply %s... %.*s" msgstr "No s'ha pogut aplicar %s... %.*s" +#: sequencer.c #, c-format msgid "Could not merge %.*s" msgstr "No s'ha pogut fusionar %.*s" +#: sequencer.c #, c-format msgid "Executing: %s\n" msgstr "S'està executant: %s\n" +#: sequencer.c #, c-format msgid "" "execution failed: %s\n" @@ -20795,9 +26796,11 @@ msgstr "" " git rebase --continue\n" "\n" +#: sequencer.c msgid "and made changes to the index and/or the working tree.\n" msgstr "i ha fet canvis a l'Ãndex i/o a l'arbre de treball.\n" +#: sequencer.c #, c-format msgid "" "execution succeeded: %s\n" @@ -20814,52 +26817,65 @@ msgstr "" " git rebase --continue\n" "\n" +#: sequencer.c #, c-format msgid "illegal label name: '%.*s'" msgstr "nom d'etiqueta no permès: «%.*s»" +#: sequencer.c #, c-format msgid "could not resolve '%s'" msgstr "no s'ha pogut resoldre «%s»" +#: sequencer.c msgid "writing fake root commit" msgstr "s'està escrivint una comissió arrel falsa" +#: sequencer.c msgid "writing squash-onto" msgstr "s'està escrivint «squash-onto»" +#: sequencer.c msgid "cannot merge without a current revision" msgstr "no es pot fusionar sense una revisió actual" +#: sequencer.c #, c-format msgid "unable to parse '%.*s'" msgstr "no s'ha pogut analitzar «%.*s»" +#: sequencer.c #, c-format msgid "nothing to merge: '%.*s'" msgstr "no hi ha res per a fusionar «%.*s»" +#: sequencer.c msgid "octopus merge cannot be executed on top of a [new root]" msgstr "" "no es pot executar la fusió «octopus» a la part superior d'una [arrel nova]" +#: sequencer.c #, c-format msgid "could not get commit message of '%s'" msgstr "no s'ha pogut llegir el missatge de comissió de «%s»" +#: sequencer.c #, c-format msgid "could not even attempt to merge '%.*s'" msgstr "no s'ha pogut fusionar «%.*s»" +#: sequencer.c msgid "merge: Unable to write new index file" msgstr "fusió: no s'ha pogut escriure un fitxer d'Ãndex nou" +#: sequencer.c #, c-format msgid "" "another 'rebase' process appears to be running; '%s.lock' already exists" msgstr "" "sembla que s'està executant un altre procés «rebase»: «%s.lock» ja existeix" +#: sequencer.c #, c-format msgid "" "Updated the following refs with %s:\n" @@ -20868,6 +26884,7 @@ msgstr "" "S'han actualitzat els següents refs amb %s:\n" "%s" +#: sequencer.c #, c-format msgid "" "Failed to update the following refs with %s:\n" @@ -20876,32 +26893,40 @@ msgstr "" "No s'han pogut actualitzar les referències següents amb %s:\n" "%s" +#: sequencer.c msgid "Cannot autostash" msgstr "No es pot fer un «stash» automà ticament" +#: sequencer.c #, c-format msgid "Unexpected stash response: '%s'" msgstr "Resposta de «stash» inesperada: «%s»" +#: sequencer.c #, c-format msgid "Could not create directory for '%s'" msgstr "No s'ha pogut crear el directori per a «%s»" +#: sequencer.c #, c-format msgid "Created autostash: %s\n" msgstr "S'ha creat un «stash» automà ticament: %s\n" +#: sequencer.c msgid "could not reset --hard" msgstr "no s'ha pogut fer reset --hard" +#: sequencer.c #, c-format msgid "Applied autostash.\n" msgstr "S'ha aplicat el «stash» automà ticament.\n" +#: sequencer.c #, c-format msgid "cannot store %s" msgstr "no es pot emmagatzemar %s" +#: sequencer.c #, c-format msgid "" "%s\n" @@ -20912,27 +26937,34 @@ msgstr "" "Els vostres canvis estan segurs en el «stash».\n" "Podeu executar «git stash pop» o «git stash drop» en qualsevol moment.\n" +#: sequencer.c msgid "Applying autostash resulted in conflicts." msgstr "L'aplicació del «stash» automà ticament ha donat conflictes." +#: sequencer.c msgid "Autostash exists; creating a new stash entry." msgstr "" "El «stash» automà tic ja existeix; s'està creant una entrada «stash» nova." +#: sequencer.c msgid "autostash reference is a symref" msgstr "la referència d'autostash és un symref" +#: sequencer.c msgid "could not detach HEAD" msgstr "no s'ha pogut separar HEAD" +#: sequencer.c #, c-format msgid "Stopped at HEAD\n" msgstr "Aturat a HEAD\n" +#: sequencer.c #, c-format msgid "Stopped at %s\n" msgstr "Aturat a %s\n" +#: sequencer.c #, c-format msgid "" "Could not execute the todo command\n" @@ -20953,46 +26985,58 @@ msgstr "" " git rebase --edit-todo\n" " git rebase --continue\n" +#: sequencer.c #, c-format msgid "Stopped at %s... %.*s\n" msgstr "Aturat a %s... %.*s\n" +#: sequencer.c #, c-format msgid "Rebasing (%d/%d)%s" msgstr "S'està fent «rebase» (%d/%d)%s" +#: sequencer.c #, c-format msgid "unknown command %d" msgstr "ordre %d desconeguda" +#: sequencer.c msgid "could not read orig-head" msgstr "no s'ha pogut llegir orig-head" +#: sequencer.c msgid "could not read 'onto'" msgstr "no s'ha pogut llegir «onto»" +#: sequencer.c #, c-format msgid "could not update HEAD to %s" msgstr "no s'ha pogut actualitzar HEAD a %s" +#: sequencer.c #, c-format msgid "Successfully rebased and updated %s.\n" msgstr "S'ha fet «rebase» i actualitzat %s amb èxit.\n" +#: sequencer.c msgid "cannot rebase: You have unstaged changes." msgstr "no es pot fer «rebase»: teniu canvis «unstaged»." +#: sequencer.c msgid "cannot amend non-existing commit" msgstr "no es pot esmenar una comissió no existent" +#: sequencer.c #, c-format msgid "invalid file: '%s'" msgstr "fitxer no và lid: «%s»" +#: sequencer.c #, c-format msgid "invalid contents: '%s'" msgstr "contingut no và lid: «%s»" +#: sequencer.c msgid "" "\n" "You have uncommitted changes in your working tree. Please, commit them\n" @@ -21002,57 +27046,73 @@ msgstr "" "Teniu canvis no comesos en el vostre arbre de treball. \n" "Cometeu-los primer i després executeu «git rebase --continue» de nou." +#: sequencer.c #, c-format msgid "could not write file: '%s'" msgstr "no s'ha pogut escriure el fitxer: «%s»" +#: sequencer.c msgid "could not remove CHERRY_PICK_HEAD" msgstr "no s'ha pogut eliminar CHERRY_PICK_HEAD" +#: sequencer.c msgid "could not commit staged changes." msgstr "no s'han pogut cometre els canvis «staged»." +#: sequencer.c #, c-format msgid "%s: can't cherry-pick a %s" msgstr "%s: no es pot fer «cherry pick» a %s" +#: sequencer.c #, c-format msgid "%s: bad revision" msgstr "%s: revisió incorrecta" +#: sequencer.c msgid "can't revert as initial commit" msgstr "no es pot revertir com a comissió inicial" +#: sequencer.c #, c-format msgid "skipped previously applied commit %s" msgstr "omet les comissions aplicades anteriorment %s" +#: sequencer.c msgid "use --reapply-cherry-picks to include skipped commits" msgstr "useu --reapply-cherry-picks per a incloure les comissions omeses" +#: sequencer.c msgid "make_script: unhandled options" msgstr "make_script: opcions no gestionades" +#: sequencer.c msgid "make_script: error preparing revisions" msgstr "make_script: s'ha produït un error en preparar les revisions" +#: sequencer.c msgid "nothing to do" msgstr "res a fer" +#: sequencer.c msgid "could not skip unnecessary pick commands" msgstr "no s'han pogut ometre les ordres «picks» no necessà ries" +#: sequencer.c msgid "the script was already rearranged." msgstr "l'script ja estava endreçat." +#: sequencer.c #, c-format msgid "update-refs file at '%s' is invalid" msgstr "el fitxer update-refs a «%s» no és và lid" +#: setup.c #, c-format msgid "'%s' is outside repository at '%s'" msgstr "«%s» està fora del repositori a «%s»" +#: setup.c #, c-format msgid "" "%s: no such path in the working tree.\n" @@ -21062,6 +27122,7 @@ msgstr "" "Useu «git <ordre> -- <camÃ>...» per a especificar camins que no existeixin " "localment." +#: setup.c #, c-format msgid "" "ambiguous argument '%s': unknown revision or path not in the working tree.\n" @@ -21073,10 +27134,12 @@ msgstr "" "Useu «--» per a separar els camins de les revisions:\n" "«git <ordre> [<revisió>...] -- [<fitxer>...]»" +#: setup.c #, c-format msgid "option '%s' must come before non-option arguments" msgstr "l'opció «%s» ha d'aparèixer abans que els arguments opcionals" +#: setup.c #, c-format msgid "" "ambiguous argument '%s': both revision and filename\n" @@ -21087,79 +27150,121 @@ msgstr "" "Useu «--» per a separar els camins de les revisions:\n" "«git <ordre> [<revisió>...] -- [<fitxer>...]»" +#: setup.c msgid "unable to set up work tree using invalid config" msgstr "" "no s'ha pogut configurar un arbre de treball utilitzant una configuració no " "và lida" +#: setup.c +#, c-format +msgid "'%s' already specified as '%s'" +msgstr "«%s» ja especificat com a «%s»" + +#: setup.c #, c-format msgid "Expected git repo version <= %d, found %d" msgstr "S'esperava una versió de repositori de git <= %d, s'ha trobat %d" +#: setup.c msgid "unknown repository extension found:" msgid_plural "unknown repository extensions found:" msgstr[0] "s'ha trobat una extensió de repositori desconeguda:" msgstr[1] "s'han trobat extensions de repositori desconegudes:" +#: setup.c msgid "repo version is 0, but v1-only extension found:" msgid_plural "repo version is 0, but v1-only extensions found:" msgstr[0] "el repositori és versió 0, però només s'han trobat una extensió v1:" msgstr[1] "el repositori és versió 0, però només s'han trobat extensions v1:" +#: setup.c #, c-format msgid "error opening '%s'" msgstr "s'ha produït un error en obrir «%s»" +#: setup.c #, c-format msgid "too large to be a .git file: '%s'" msgstr "massa gran per a ser un fitxer .git: «%s»" +#: setup.c #, c-format msgid "error reading %s" msgstr "error en llegir %s" +#: setup.c #, c-format msgid "invalid gitfile format: %s" msgstr "format gitfile no và lid: %s" +#: setup.c #, c-format msgid "no path in gitfile: %s" msgstr "sense camà al gitfile: %s" +#: setup.c #, c-format msgid "not a git repository: %s" msgstr "no és un repositori de git: %s" +#: setup.c #, c-format msgid "'$%s' too big" msgstr "«$%s» massa gran" +#: setup.c #, c-format msgid "not a git repository: '%s'" msgstr "no és un repositori de git: «%s»" +#: setup.c #, c-format msgid "cannot chdir to '%s'" msgstr "no es pot canviar de directori a «%s»" +#: setup.c msgid "cannot come back to cwd" msgstr "no es pot tornar al directori de treball actual" +#: setup.c #, c-format msgid "failed to stat '%*s%s%s'" msgstr "s'ha produït un error en fer stat a «%*s%s%s»" +#: setup.c +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "el safe.directory «%s» no és absolut" + +#: setup.c +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"s'ha detectat una propietat dubtosa al repositori a «%s»\n" +"%sPer a afegir una excepció per a aquest directori, executeu:\n" +"\n" +"\tgit config --global --add safe.directory %s" + +#: setup.c msgid "Unable to read current working directory" msgstr "No s'ha pogut llegir el directori de treball actual" +#: setup.c #, c-format msgid "cannot change to '%s'" msgstr "no es pot canviar a «%s»" +#: setup.c #, c-format msgid "not a git repository (or any of the parent directories): %s" msgstr "no és un repositori de git (ni cap dels directoris pares): %s" +#: setup.c #, c-format msgid "" "not a git repository (or any parent up to mount point %s)\n" @@ -21170,22 +27275,12 @@ msgstr "" "S'atura a la frontera de sistema de fitxers (GIT_DISCOVERY_ACROSS_FILESYSTEM " "no està establert)." -#, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"s'ha detectat una propietat dubtosa al repositori a «%s»\n" -"%sPer a afegir una excepció per a aquest directori, executeu:\n" -"\n" -"\tgit config --global --add safe.directory %s" - +#: setup.c #, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "no es pot utilitzar el dipòsit nu «%s» (safe.bareRepository és «%s»)" +#: setup.c #, c-format msgid "" "problem with core.sharedRepository filemode value (0%.3o).\n" @@ -21196,185 +27291,246 @@ msgstr "" "El propietari dels fitxers sempre ha de tenir permisos de lectura i " "escriptura." +#: setup.c msgid "fork failed" msgstr "el «fork» ha fallat" +#: setup.c msgid "setsid failed" msgstr "«setsid» ha fallat" +#: setup.c #, c-format msgid "cannot stat template '%s'" msgstr "no es pot fer stat en la plantilla «%s»" +#: setup.c #, c-format msgid "cannot opendir '%s'" msgstr "no es pot fer opendir en el directori «%s»" +#: setup.c #, c-format msgid "cannot readlink '%s'" msgstr "no es pot fer readlink en «%s»" +#: setup.c #, c-format msgid "cannot symlink '%s' '%s'" msgstr "no es pot fer symlink en «%s» «%s»" +#: setup.c #, c-format msgid "cannot copy '%s' to '%s'" msgstr "no es pot copiar «%s» a «%s»" +#: setup.c #, c-format msgid "ignoring template %s" msgstr "s'està ignorant la plantilla %s" +#: setup.c #, c-format msgid "templates not found in %s" msgstr "plantilles no trobades a %s" +#: setup.c #, c-format msgid "not copying templates from '%s': %s" msgstr "no s'estan copiant plantilles de «%s»: %s" +#: setup.c #, c-format msgid "invalid initial branch name: '%s'" msgstr "nom de branca inicial no và lid: «%s»" +#: setup.c #, c-format msgid "re-init: ignored --initial-branch=%s" msgstr "reinicialització: s'ha ignorat --initial-branch=%s" +#: setup.c #, c-format msgid "unable to handle file type %d" msgstr "no s'ha pogut gestionar el tipus de fitxer %d" +#: setup.c #, c-format msgid "unable to move %s to %s" msgstr "no s'ha pogut moure %s a %s" +#: setup.c msgid "attempt to reinitialize repository with different hash" msgstr "s'ha intentat reinicialitzar el repositori amb un resum diferent" +#: setup.c msgid "" "attempt to reinitialize repository with different reference storage format" msgstr "" "s'ha intentat reactivar el repositori amb un format d'emmagatzematge de " "referència diferent" +#: setup.c #, c-format msgid "%s already exists" msgstr "%s ja existeix" +#: setup.c #, c-format msgid "Reinitialized existing shared Git repository in %s%s\n" msgstr "S'ha reinicialitzat el repositori compartit existent del Git en %s%s\n" +#: setup.c #, c-format msgid "Reinitialized existing Git repository in %s%s\n" msgstr "S'ha reinicialitzat el repositori existent del Git en %s%s\n" +#: setup.c #, c-format msgid "Initialized empty shared Git repository in %s%s\n" msgstr "S'ha inicialitzat un repositori compartit buit del Git en %s%s\n" +#: setup.c #, c-format msgid "Initialized empty Git repository in %s%s\n" msgstr "S'ha inicialitzat un repositori buit del Git en %s%s\n" +#: sparse-index.c #, c-format msgid "index entry is a directory, but not sparse (%08x)" msgstr "l'entrada d'Ãndex és un directori, però no dispers (%08x)" +#: split-index.c msgid "cannot use split index with a sparse index" msgstr "no es pot utilitzar l'Ãndex partit amb un Ãndex dispers" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "format %s incorrecte: l'element «%s» no comença amb «(»" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "format %s incorrecte: l'element «%s» no acaba en «)»" + +#. TRANSLATORS: %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "format %s incorrecte: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte +#: strbuf.c #, c-format msgid "%u.%2.2u GiB" msgstr "%u.%2.2u GiB" #. TRANSLATORS: IEC 80000-13:2008 gibibyte/second +#: strbuf.c #, c-format msgid "%u.%2.2u GiB/s" msgstr "%u.%2.2u GiB/s" #. TRANSLATORS: IEC 80000-13:2008 mebibyte +#: strbuf.c #, c-format msgid "%u.%2.2u MiB" msgstr "%u.%2.2u MiB" #. TRANSLATORS: IEC 80000-13:2008 mebibyte/second +#: strbuf.c #, c-format msgid "%u.%2.2u MiB/s" msgstr "%u.%2.2u MiB/s" #. TRANSLATORS: IEC 80000-13:2008 kibibyte +#: strbuf.c #, c-format msgid "%u.%2.2u KiB" msgstr "%u.%2.2u KiB" #. TRANSLATORS: IEC 80000-13:2008 kibibyte/second +#: strbuf.c #, c-format msgid "%u.%2.2u KiB/s" msgstr "%u.%2.2u KiB/s" #. TRANSLATORS: IEC 80000-13:2008 byte +#: strbuf.c #, c-format msgid "%u byte" msgid_plural "%u bytes" -msgstr[0] "%u byte" -msgstr[1] "%u bytes" +msgstr[0] "%u octet" +msgstr[1] "%u octets" #. TRANSLATORS: IEC 80000-13:2008 byte/second +#: strbuf.c #, c-format msgid "%u byte/s" msgid_plural "%u bytes/s" -msgstr[0] "%u byte/s" -msgstr[1] "%u bytes/s" +msgstr[0] "%u octet/s" +msgstr[1] "%u octets/s" +#: submodule-config.c #, c-format msgid "ignoring suspicious submodule name: %s" msgstr "s'està ignorant el nom de submòdul sospitós %s" +#: submodule-config.c msgid "negative values not allowed for submodule.fetchJobs" msgstr "no es permeten els valors negatius a submodule.fetchJobs" +#: submodule-config.c #, c-format msgid "ignoring '%s' which may be interpreted as a command-line option: %s" msgstr "" "s'està ignorant «%s» que pot interpretar-se com a una opció de lÃnia " "d'ordres: %s" +#: submodule-config.c #, c-format msgid "Could not update .gitmodules entry %s" msgstr "No s'ha pogut actualitzar l'entrada de .gitmodules %s" +#: submodule.c msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" msgstr "" "No es pot canviar un .gitmodules no fusionat, primer resoleu els conflictes " "de fusió" +#: submodule.c #, c-format msgid "Could not find section in .gitmodules where path=%s" msgstr "No s'ha pogut trobar la secció en .gitmodules on path=%s" +#: submodule.c #, c-format msgid "Could not remove .gitmodules entry for %s" msgstr "No s'ha pogut eliminar l'entrada de .gitmodules per a %s" +#: submodule.c msgid "staging updated .gitmodules failed" msgstr "l'allistament del .gitmodules actualitzat ha fallat" +#: submodule.c #, c-format msgid "in unpopulated submodule '%s'" msgstr "al submòdul sense popular «%s»" +#: submodule.c #, c-format msgid "Pathspec '%s' is in submodule '%.*s'" msgstr "L'especificació «%s» és en el submòdul «%.*s»" +#: submodule.c #, c-format msgid "bad --ignore-submodules argument: %s" msgstr "argument incorrecte --ignore-submodules: %s" +#: submodule.c #, c-format msgid "" "Submodule in commit %s at path: '%s' collides with a submodule named the " @@ -21383,10 +27539,12 @@ msgstr "" "El submòdul en la comissió %s al camÃ: «%s» col·lideix amb un submòdul amb " "el mateix nom. Ometent-lo." +#: submodule.c #, c-format msgid "submodule entry '%s' (%s) is a %s, not a commit" msgstr "l'entrada del submòdul «%s» (%s) és a %s, no és una comissió" +#: submodule.c #, c-format msgid "" "Could not run 'git rev-list <commits> --not --remotes -n 1' command in " @@ -21395,34 +27553,42 @@ msgstr "" "No s'ha pogut executar l'ordre «git rev-list <commits> --not --remotes -n 1» " "en el submòdul %s" +#: submodule.c #, c-format msgid "process for submodule '%s' failed" msgstr "ha fallat el procés per al submòdul «%s»" +#: submodule.c #, c-format msgid "Pushing submodule '%s'\n" msgstr "S'està pujant el submòdul «%s»\n" +#: submodule.c #, c-format msgid "Unable to push submodule '%s'\n" msgstr "No s'ha pogut pujar el submòdul «%s»\n" +#: submodule.c #, c-format msgid "Fetching submodule %s%s\n" msgstr "S'està obtenint el submòdul %s%s\n" +#: submodule.c #, c-format msgid "Could not access submodule '%s'\n" msgstr "No s'ha pogut accedir al submòdul «%s»\n" +#: submodule.c #, c-format msgid "Could not access submodule '%s' at commit %s\n" msgstr "No s'ha pogut accedir al submòdul «%s» en la comissió %s\n" +#: submodule.c #, c-format msgid "Fetching submodule %s%s at commit %s\n" msgstr "S'està obtenint el submòdul %s%s en la comissió %s\n" +#: submodule.c #, c-format msgid "" "Errors during submodule fetch:\n" @@ -21431,51 +27597,74 @@ msgstr "" "Errors durant l'obtenció de submòduls:\n" "%s" +#: submodule.c #, c-format msgid "'%s' not recognized as a git repository" msgstr "«%s» no reconegut com un repositori git" +#: submodule.c #, c-format msgid "Could not run 'git status --porcelain=2' in submodule %s" msgstr "No s'ha pogut executar «git status --porcelain=2» en el submòdul %s" +#: submodule.c #, c-format msgid "'git status --porcelain=2' failed in submodule %s" msgstr "«git status --porcelain=2» ha fallat en el submòdul %s" +#: submodule.c #, c-format msgid "could not start 'git status' in submodule '%s'" msgstr "no s'ha pogut iniciar «git status» al submòdul «%s»" +#: submodule.c #, c-format msgid "could not run 'git status' in submodule '%s'" msgstr "no s'ha pogut executar «git status» al submòdul «%s»" +#: submodule.c #, c-format msgid "Could not unset core.worktree setting in submodule '%s'" msgstr "" "No s'ha pogut desassignar el parà metre «core.worktree» al submòdul «%s»" +#: submodule.c #, c-format msgid "could not recurse into submodule '%s'" msgstr "" "s'ha produït un error en cercar recursivament al camà del submòdul «%s»" +#: submodule.c msgid "could not reset submodule index" msgstr "no s'ha pogut restablir l'Ãndex del submòdul" +#: submodule.c #, c-format msgid "submodule '%s' has dirty index" msgstr "el submòdul «%s» té l'Ãndex brut" +#: submodule.c #, c-format msgid "Submodule '%s' could not be updated." msgstr "No s'ha pogut actualitzar el submòdul «%s»." +#: submodule.c #, c-format msgid "submodule git dir '%s' is inside git dir '%.*s'" msgstr "submodule git dir «%s» està dins git dir «%.*s»" +#: submodule.c +#, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"s'esperava que «%.*s» en el camà del submòdul «%s» no fos un enllaç simbòlic" + +#: submodule.c +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "s'esperava que el camà del submòdul «%s» no fos un enllaç simbòlic" + +#: submodule.c #, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" @@ -21483,14 +27672,17 @@ msgstr "" "no està admès relocate_gitdir per al submòdul «%s» amb més d'un arbre de " "treball" +#: submodule.c #, c-format msgid "could not lookup name for submodule '%s'" msgstr "no s'ha trobat el nom pel submòdul «%s»" +#: submodule.c #, c-format msgid "refusing to move '%s' into an existing git dir" msgstr "s'ha refusat moure «%s» a un directori git existent" +#: submodule.c #, c-format msgid "" "Migrating git directory of '%s%s' from\n" @@ -21501,150 +27693,186 @@ msgstr "" "«%s» a\n" "«%s»\n" +#: submodule.c msgid "could not start ls-files in .." msgstr "no s'ha pogut iniciar ls-files a .." +#: submodule.c #, c-format msgid "ls-tree returned unexpected return code %d" msgstr "ls-tree ha retornat un codi de retorn %d no esperat" +#: symlinks.c #, c-format msgid "failed to lstat '%s'" msgstr "s'ha produït un error en fer lstat a «%s»" +#: t/helper/test-bundle-uri.c msgid "no remote configured to get bundle URIs from" msgstr "no hi ha cap remot configurat per a obtenir els URI del paquet" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "el remot «%s» no té cap URL configurat" - +#: t/helper/test-bundle-uri.c msgid "could not get the bundle-uri list" msgstr "no s'ha pogut obtenir la llista bundle-uri" +#: t/helper/test-cache-tree.c msgid "test-tool cache-tree <options> (control|prime|update)" msgstr "test-tool cache-tree <opcions> (control|prime|update)" +#: t/helper/test-cache-tree.c msgid "clear the cache tree before each iteration" msgstr "neteja l'arbre de la memòria cau abans de cada iteració" +#: t/helper/test-cache-tree.c msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "" "nombre d'entrades a l'arbre de la memòria cau a invalidar (per defecte 0)" +#: t/helper/test-reach.c #, c-format msgid "commit %s is not marked reachable" msgstr "la comissió %s no està marcada com abastable" +#: t/helper/test-reach.c msgid "too many commits marked reachable" msgstr "hi ha massa comissions marcades com abastables" +#: t/helper/test-serve-v2.c msgid "test-tool serve-v2 [<options>]" msgstr "test-tool serve-v2 [<opcions>]" +#: t/helper/test-serve-v2.c msgid "exit immediately after advertising capabilities" msgstr "surt immediatament després d'anunciar les funcionalitats" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc is-active [<name>] [<options>]" msgstr "test-helper simple-ipc is-active [<nom>] [<opcions>]" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc run-daemon [<name>] [<threads>]" msgstr "test-helper simple-ipc run-daemon [<nom>] [<fils>]" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc start-daemon [<name>] [<threads>] [<max-wait>]" msgstr "test-helper simple-ipc start-daemon [<nom>] [<fils>] [<max-wait>]" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc stop-daemon [<name>] [<max-wait>]" msgstr "test-helper simple-ipc stop-daemon [<nom>] [<max-wait>]" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc send [<name>] [<token>]" msgstr "test-helper simple-ipc send [<nom>] [<testimoni>]" +#: t/helper/test-simple-ipc.c msgid "test-helper simple-ipc sendbytes [<name>] [<bytecount>] [<byte>]" -msgstr "test-helper simple-ipc sendbytes [<nom>] [<bytecount>] [<byte>]" +msgstr "" +"test-helper simple-ipc sendbytes [<nom>] [<recompte-octets>] [<octet>]" +#: t/helper/test-simple-ipc.c msgid "" "test-helper simple-ipc multiple [<name>] [<threads>] [<bytecount>] " "[<batchsize>]" msgstr "" -"test-helper simple-ipc multiple [<nom>] [<fils>] [<bytecount>] " -"[<batchsize>]" +"test-helper simple-ipc multiple [<nom>] [<fils>] [<recompte-octets>] " +"[<mida-lot>]" +#: t/helper/test-simple-ipc.c msgid "name or pathname of unix domain socket" msgstr "nom o nom de camà del sòcol de domini unix" +#: t/helper/test-simple-ipc.c msgid "named-pipe name" msgstr "nom del conducte amb nom" +#: t/helper/test-simple-ipc.c msgid "number of threads in server thread pool" msgstr "nombre de fils en el conjunt de fils del servidor" +#: t/helper/test-simple-ipc.c msgid "seconds to wait for daemon to start or stop" msgstr "segons a esperar que el dimoni comenci o s'aturi" +#: t/helper/test-simple-ipc.c msgid "number of bytes" msgstr "nombre d'octets" +#: t/helper/test-simple-ipc.c msgid "number of requests per thread" msgstr "nombre de peticions per fil" +#: t/helper/test-simple-ipc.c msgid "byte" msgstr "octet" +#: t/helper/test-simple-ipc.c msgid "ballast character" msgstr "carà cter de llast" +#: t/helper/test-simple-ipc.c msgid "token" msgstr "testimoni" +#: t/helper/test-simple-ipc.c msgid "command token to send to the server" msgstr "testimoni d'ordre a enviar al servidor" +#: t/unit-tests/unit-test.c +msgid "unit-test [<options>]" +msgstr "unit-test [<opcions>]" + +#: t/unit-tests/unit-test.c +msgid "immediately exit upon the first failed test" +msgstr "sortir immediatament en fallar el primer test" + +# deixada sense traduir perquè pareix opció i no text +#: t/unit-tests/unit-test.c +msgid "suite[::test]" +msgstr "suite[::test]" + +#: t/unit-tests/unit-test.c +msgid "run only test suite or individual test <suite[::test]>" +msgstr "" +"executa només el conjunt de proves o la prova individual <suite[::test]>" + +#: t/unit-tests/unit-test.c +msgid "suite" +msgstr "suite" + +#: t/unit-tests/unit-test.c +msgid "exclude test suite <suite>" +msgstr "exclou conjunt de proves <conjunt>" + +#: trailer.c #, c-format msgid "running trailer command '%s' failed" msgstr "l'execució de l'ordre «trailer» «%s» ha fallat" +#: trailer.c #, c-format msgid "unknown value '%s' for key '%s'" msgstr "valor desconegut «%s» per a la clau «%s»" +#: trailer.c #, c-format msgid "empty trailer token in trailer '%.*s'" msgstr "testimoni de «trailer» buit en el «trailer» «%.*s»" -#, c-format -msgid "could not read input file '%s'" -msgstr "no s'ha pogut llegir el fitxer d'entrada «%s»" - -#, c-format -msgid "could not stat %s" -msgstr "no s'ha pogut fer stat a %s" - -#, c-format -msgid "file %s is not a regular file" -msgstr "el fitxer %s no és un fitxer regular" - -#, c-format -msgid "file %s is not writable by user" -msgstr "el fitxer %s no és gravable per l'usuari" - -msgid "could not open temporary file" -msgstr "no s'ha pogut obrir el fitxer temporal" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "no s'ha pogut canviar el nom del fitxer temporal a %s" - +#: transport-helper.c msgid "full write to remote helper failed" msgstr "l'escriptura completa a l'ajudant remot ha fallat" +#: transport-helper.c #, c-format msgid "unable to find remote helper for '%s'" msgstr "no s'ha pogut trobar l'ajudant remot per a «%s»" +#: transport-helper.c msgid "can't dup helper output fd" msgstr "no es pot duplicar la sortida de l'ajudant «fd»" +#: transport-helper.c #, c-format msgid "" "unknown mandatory capability %s; this remote helper probably needs newer " @@ -21653,93 +27881,118 @@ msgstr "" "funcionalitat obligatòria %s desconeguda; aquest ajudant remot probablement " "necessita una versió més nova del Git" +#: transport-helper.c msgid "this remote helper should implement refspec capability" msgstr "aquest ajudant remot ha d'implementar la funcionalitat de refspec" +#: transport-helper.c #, c-format msgid "%s unexpectedly said: '%s'" msgstr "%s ha dit inesperadament «%s»" +#: transport-helper.c #, c-format msgid "%s also locked %s" msgstr "%s també està bloquejat %s" +#: transport-helper.c msgid "couldn't run fast-import" msgstr "no s'ha pogut executar «fast-import»" +#: transport-helper.c msgid "error while running fast-import" msgstr "error en executar la importació rà pida" +#: transport-helper.c #, c-format msgid "could not read ref %s" msgstr "no s'ha pogut llegir la referència %s" +#: transport-helper.c #, c-format msgid "unknown response to connect: %s" msgstr "resposta desconeguda en connectar: %s" +#: transport-helper.c msgid "setting remote service path not supported by protocol" msgstr "el protocol no permet establir el camà del servei remot" +#: transport-helper.c msgid "invalid remote service path" msgstr "el camà del servei remot no és và lid" +#: transport-helper.c #, c-format msgid "can't connect to subservice %s" msgstr "no es pot connectar al subservei %s" +#: transport-helper.c transport.c msgid "--negotiate-only requires protocol v2" msgstr "--negotiate-only requereix el protocol v2" +#: transport-helper.c msgid "'option' without a matching 'ok/error' directive" msgstr "«option» sense una directiva «ok/error» coincident" +#: transport-helper.c #, c-format msgid "expected ok/error, helper said '%s'" msgstr "s'esperava error/OK, l'ajudant ha dit «%s»" +#: transport-helper.c #, c-format msgid "helper reported unexpected status of %s" msgstr "l'ajudant ha informat d'un estat inesperat de %s" +#: transport-helper.c #, c-format msgid "helper %s does not support dry-run" msgstr "l'ajudant %s no admet dry-run" +#: transport-helper.c #, c-format msgid "helper %s does not support --signed" msgstr "l'ajudant %s no admet --signed" +#: transport-helper.c #, c-format msgid "helper %s does not support --signed=if-asked" msgstr "l'ajudant %s no admet --signed=if-asked" +#: transport-helper.c #, c-format msgid "helper %s does not support --atomic" msgstr "l'ajudant %s no admet --atomic" +#: transport-helper.c #, c-format msgid "helper %s does not support --%s" msgstr "l'ajudant %s no admet --%s" +#: transport-helper.c #, c-format msgid "helper %s does not support 'push-option'" msgstr "l'ajudant %s no admet «push-option»" +#: transport-helper.c msgid "remote-helper doesn't support push; refspec needed" msgstr "" -"remot-helper no permet pujar; es necessiten especificacions de referència" +"remote-helper no permet pujar; es necessiten especificacions de referència" +#: transport-helper.c #, c-format -msgid "helper %s does not support 'force'" -msgstr "l'ajudant %s no admet «force»" +msgid "helper %s does not support '--force'" +msgstr "l'ajudant %s no admet «--force»" +#: transport-helper.c msgid "couldn't run fast-export" msgstr "no s'ha pogut executar l'exportació rà pida" +#: transport-helper.c msgid "error while running fast-export" msgstr "error en executar l'exportació rà pida" +#: transport-helper.c #, c-format msgid "" "No refs in common and none specified; doing nothing.\n" @@ -21748,80 +28001,101 @@ msgstr "" "No hi ha referències en comú i no n'hi ha cap d'especificada.\n" "No es farà res. Potser haurÃeu d'especificar una branca.\n" +#: transport-helper.c #, c-format msgid "unsupported object format '%s'" msgstr "format d'objecte no suportat «%s»" +#: transport-helper.c #, c-format msgid "malformed response in ref list: %s" msgstr "resposta mal formada al llistat de referències: %s" +#: transport-helper.c #, c-format msgid "read(%s) failed" msgstr "ha fallat la lectura(%s)" +#: transport-helper.c #, c-format msgid "write(%s) failed" msgstr "ha fallat l'escriptura(%s)" +#: transport-helper.c #, c-format msgid "%s thread failed" msgstr "%s ha fallat el fil" +#: transport-helper.c #, c-format msgid "%s thread failed to join: %s" msgstr "el fil %s no s'ha pogut unir: %s" +#: transport-helper.c #, c-format msgid "can't start thread for copying data: %s" msgstr "no es pot iniciar el fil per a copiar les dades: %s" +#: transport-helper.c #, c-format msgid "%s process failed to wait" msgstr "el procés %s no ha pogut esperar" +#: transport-helper.c #, c-format msgid "%s process failed" msgstr "el procés %s ha fallat" +#: transport-helper.c msgid "can't start thread for copying data" msgstr "no es pot iniciar el fil per a copiar dades" +#: transport.c #, c-format msgid "Would set upstream of '%s' to '%s' of '%s'\n" msgstr "Canviaria la font de «%s» a «%s» de «%s»\n" +#: transport.c #, c-format msgid "could not read bundle '%s'" msgstr "no s'ha pogut llegir el farcell «%s»" +#: transport.c #, c-format msgid "transport: invalid depth option '%s'" msgstr "transport: opció de profunditat no và lida «%s»" +#: transport.c msgid "see protocol.version in 'git help config' for more details" msgstr "vegeu «protocol.version» a «git help config» per a més detalls" +#: transport.c msgid "server options require protocol version 2 or later" msgstr "les opcions del servidor requereixen el protocol versió 2 o posterior" +#: transport.c msgid "server does not support wait-for-done" msgstr "el servidor no admet «wait-for-done»" +#: transport.c msgid "could not parse transport.color.* config" msgstr "no s'ha pogut analitzar la configuració de transport.color.*" +#: transport.c msgid "support for protocol v2 not implemented yet" msgstr "" "encara no s'ha implementat la compatibilitat amb la versió v2 del protocol" +#: transport.c #, c-format msgid "transport '%s' not allowed" msgstr "no es permet el transport «%s»" +#: transport.c msgid "git-over-rsync is no longer supported" msgstr "git-over-rsync ja no s'admet" +#: transport.c #, c-format msgid "" "The following submodule paths contain changes that can\n" @@ -21830,6 +28104,7 @@ msgstr "" "Els camins de submòdul següents contenen canvis que no\n" "es poden trobar en cap remot:\n" +#: transport.c #, c-format msgid "" "\n" @@ -21855,34 +28130,44 @@ msgstr "" "\n" "per a pujar-los a un remot.\n" +#: transport.c msgid "Aborting." msgstr "S'està avortant." +#: transport.c msgid "failed to push all needed submodules" msgstr "no s'han pogut pujar tots els submòduls necessaris" +#: transport.c msgid "bundle-uri operation not supported by protocol" msgstr "L'operació bundle-uri no és compatible amb el protocol" +#: transport.c msgid "could not retrieve server-advertised bundle-uri list" msgstr "" "no s'ha pogut recuperar la llista de paquets d'URI anunciats pel servidor" +#: transport.c msgid "operation not supported by protocol" msgstr "opció no admesa pel protocol" +#: tree-walk.c msgid "too-short tree object" msgstr "objecte d'arbre massa curt" +#: tree-walk.c msgid "malformed mode in tree entry" msgstr "mode mal format en entrada d'arbre" +#: tree-walk.c msgid "empty filename in tree entry" msgstr "nom de fitxer buit en una entrada d'arbre" +#: tree-walk.c msgid "too-short tree file" msgstr "fitxer d'arbre massa curt" +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by checkout:\n" @@ -21891,6 +28176,7 @@ msgstr "" "Els canvis locals als fitxers següents se sobreescriurien per a agafar:\n" "%%sCometeu els vostres canvis o feu «stash» abans de canviar de branca." +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by checkout:\n" @@ -21899,6 +28185,7 @@ msgstr "" "Els canvis locals als fitxers següents se sobreescriurien per a agafar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -21907,6 +28194,7 @@ msgstr "" "Els canvis locals als fitxers següents se sobreescriurien per a fusionar:\n" "%%sCometeu els vostres canvis o feu «stash» abans de fusionar." +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -21915,6 +28203,7 @@ msgstr "" "Els canvis locals als fitxers següents se sobreescriurien per a fusionar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by %s:\n" @@ -21923,6 +28212,7 @@ msgstr "" "Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" "%%sCometeu els vostres canvis o feu «stash» abans de %s." +#: unpack-trees.c #, c-format msgid "" "Your local changes to the following files would be overwritten by %s:\n" @@ -21931,6 +28221,7 @@ msgstr "" "Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "Updating the following directories would lose untracked files in them:\n" @@ -21939,6 +28230,7 @@ msgstr "" "En actualitzar els directoris següents perdria fitxers no seguits en el:\n" "%s" +#: unpack-trees.c #, c-format msgid "" "Refusing to remove the current working directory:\n" @@ -21947,6 +28239,7 @@ msgstr "" "S'ha rebutjat suprimir el directori de treball actual:\n" "%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by checkout:\n" @@ -21956,6 +28249,7 @@ msgstr "" "agafar:\n" "%%sMoveu-los o elimineu-los abans de canviar de branca." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by checkout:\n" @@ -21965,6 +28259,7 @@ msgstr "" "agafar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by merge:\n" @@ -21974,6 +28269,7 @@ msgstr "" "fusionar:\n" "%%sMoveu-los o elimineu-los abans de fusionar." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by merge:\n" @@ -21983,6 +28279,7 @@ msgstr "" "fusionar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by %s:\n" @@ -21991,6 +28288,7 @@ msgstr "" "Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" "%%sMoveu-los o elimineu-los abans de %s." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be removed by %s:\n" @@ -21999,6 +28297,7 @@ msgstr "" "Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by " @@ -22009,6 +28308,7 @@ msgstr "" "a agafar:\n" "%%sMoveu-los o elimineu-los abans de canviar de branca." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by " @@ -22019,6 +28319,7 @@ msgstr "" "a agafar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by merge:\n" @@ -22028,6 +28329,7 @@ msgstr "" "a fusionar:\n" "%%sMoveu-los o elimineu-los abans de fusionar." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by merge:\n" @@ -22037,6 +28339,7 @@ msgstr "" "a fusionar:\n" "%%s" +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by %s:\n" @@ -22046,6 +28349,7 @@ msgstr "" "%s:\n" "%%sMoveu-los o elimineu-los abans de %s." +#: unpack-trees.c #, c-format msgid "" "The following untracked working tree files would be overwritten by %s:\n" @@ -22055,10 +28359,12 @@ msgstr "" "%s:\n" "%%s" +#: unpack-trees.c #, c-format msgid "Entry '%s' overlaps with '%s'. Cannot bind." msgstr "L'entrada «%s» encavalca amb «%s». No es pot vincular." +#: unpack-trees.c #, c-format msgid "" "Cannot update submodule:\n" @@ -22067,6 +28373,7 @@ msgstr "" "No es pot actualitzar el submòdul:\n" "%s" +#: unpack-trees.c #, c-format msgid "" "The following paths are not up to date and were left despite sparse " @@ -22077,6 +28384,7 @@ msgstr "" "patrons dispersos:\n" "%s" +#: unpack-trees.c #, c-format msgid "" "The following paths are unmerged and were left despite sparse patterns:\n" @@ -22086,6 +28394,7 @@ msgstr "" "dispersos:\n" "%s" +#: unpack-trees.c #, c-format msgid "" "The following paths were already present and thus not updated despite sparse " @@ -22096,10 +28405,12 @@ msgstr "" "malgrat els patrons dispersos.:\n" "%s" +#: unpack-trees.c #, c-format msgid "Aborting\n" msgstr "S'està avortant\n" +#: unpack-trees.c #, c-format msgid "" "After fixing the above paths, you may want to run `git sparse-checkout " @@ -22108,9 +28419,11 @@ msgstr "" "Després de corregir els camins anteriors és possible que vulgueu executar " "«git sparse-checkout reapply».\n" +#: unpack-trees.c msgid "Updating files" msgstr "S'estan actualitzant els fitxers" +#: unpack-trees.c msgid "" "the following paths have collided (e.g. case-sensitive paths\n" "on a case-insensitive filesystem) and only one from the same\n" @@ -22121,273 +28434,358 @@ msgstr "" "minúscules). Només un camà del mateix grup de col·lisió es troba a l'arbre\n" "de treball:\n" +#: unpack-trees.c msgid "Updating index flags" msgstr "Actualitzant els indicadors d'Ãndex" +#: unpack-trees.c #, c-format msgid "worktree and untracked commit have duplicate entries: %s" msgstr "" "l'arbre de treball i la comissió no seguida tenen entrades duplicades: %s" +#: upload-pack.c msgid "expected flush after fetch arguments" msgstr "s'esperava una neteja després dels arguments del «fetch»" +#: urlmatch.c msgid "invalid URL scheme name or missing '://' suffix" msgstr "l'esquema d'URL no és và lid o li manca el sufix «://»" +#: urlmatch.c #, c-format msgid "invalid %XX escape sequence" msgstr "seqüència d'escapament %XX no và lida" +#: urlmatch.c msgid "missing host and scheme is not 'file:'" msgstr "manca la mà quina i l'esquema no és «file:»" +#: urlmatch.c msgid "a 'file:' URL may not have a port number" msgstr "un URL «file:» no pot tenir número de port" +#: urlmatch.c msgid "invalid characters in host name" msgstr "hi ha carà cters no và lids en el nom de mà quina" +#: urlmatch.c msgid "invalid port number" msgstr "número de port no và lid" +#: urlmatch.c msgid "invalid '..' path segment" msgstr "segment de camà «..» no và lid" +#: usage.c +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "error: no s'ha pogut formatar el missatge: %s\n" + +#: usage.c msgid "usage: " msgstr "ús: " +#: usage.c msgid "fatal: " msgstr "fatal: " +#: usage.c msgid "error: " msgstr "error: " +#: usage.c msgid "warning: " msgstr "avÃs: " +#: walker.c msgid "Fetching objects" msgstr "S'estan obtenint objectes" +#: worktree.c #, c-format msgid "'%s' at main working tree is not the repository directory" msgstr "«%s» a l'arbre de treball principal no és al directori del repositori" +#: worktree.c #, c-format msgid "'%s' file does not contain absolute path to the working tree location" msgstr "" "El fitxer «%s» no conté el camà absolut a la ubicació de l'arbre de treball" +#: worktree.c #, c-format msgid "'%s' is not a .git file, error code %d" msgstr "«%s» no és un fitxer .git, codi d'error %d" +#: worktree.c #, c-format msgid "'%s' does not point back to '%s'" msgstr "«%s» no assenyala de tornada a «%s»" +#: worktree.c msgid "not a directory" msgstr "no és en un directori" +#: worktree.c msgid ".git is not a file" msgstr ".git no és un fitxer" +#: worktree.c msgid ".git file broken" msgstr "fitxer .git malmès" +#: worktree.c msgid ".git file incorrect" msgstr "fitxer .git incorrecte" +#: worktree.c msgid "not a valid path" msgstr "no és un camà và lid" +#: worktree.c msgid "unable to locate repository; .git is not a file" msgstr "no s'ha pogut trobar el repositori; .git no és un fitxer" +#: worktree.c msgid "unable to locate repository; .git file does not reference a repository" msgstr "" "no s'ha pogut trobar el repositori; el fitxer .git no fa referència a un " "repositori" +#: worktree.c msgid "unable to locate repository; .git file broken" msgstr "no s'ha pogut trobar el repositori; el fitxer .git està malmès" +#: worktree.c msgid "gitdir unreadable" msgstr "gitdir illegible" +#: worktree.c msgid "gitdir incorrect" msgstr "gitdir incorrecte" +#: worktree.c msgid "not a valid directory" msgstr "no és en un directori và lid" +#: worktree.c msgid "gitdir file does not exist" msgstr "el fitxer gitdir no existeix" +#: worktree.c #, c-format msgid "unable to read gitdir file (%s)" msgstr "no s'ha pogut llegir el fitxer gitdir (%s)" +#: worktree.c #, c-format msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)" -msgstr "lectura curta (s'esperaven %<PRIuMAX> bytes, llegits %<PRIuMAX>)" +msgstr "lectura curta (s'esperaven %<PRIuMAX> octets, s'han llegit %<PRIuMAX>)" +#: worktree.c msgid "invalid gitdir file" msgstr "fitxer gitdir no và lid" +#: worktree.c msgid "gitdir file points to non-existent location" msgstr "el fitxer gitdir indica una ubicació no existent" +#: worktree.c #, c-format msgid "unable to set %s in '%s'" msgstr "no s'han pogut establir %s en «%s»" +#: worktree.c #, c-format msgid "unable to unset %s in '%s'" msgstr "no s'ha pogut desassignar %s en «%s»" +#: worktree.c msgid "failed to set extensions.worktreeConfig setting" msgstr "no s'ha pogut establir el parà metre extensions.worktreeConfig" +#: wrapper.c #, c-format msgid "could not setenv '%s'" msgstr "no s'ha pogut fer setenv «%s»" +#: wrapper.c #, c-format msgid "unable to create '%s'" msgstr "no s'ha pogut crear «%s»" +#: wrapper.c #, c-format msgid "could not open '%s' for reading and writing" msgstr "no s'ha pogut obrir «%s» per a lectura i escriptura" +#: wrapper.c #, c-format msgid "unable to access '%s'" msgstr "no s'ha pogut accedir a «%s»" +#: wrapper.c msgid "unable to get current working directory" msgstr "no s'ha pogut obtenir el directori de treball actual" +#: wrapper.c msgid "unable to get random bytes" -msgstr "no s'han pogut obtenir bytes aleatoris" +msgstr "no s'han pogut obtenir octets aleatoris" +#: wt-status.c msgid "Unmerged paths:" msgstr "Camins sense fusionar:" +#: wt-status.c msgid " (use \"git restore --staged <file>...\" to unstage)" msgstr " (useu «git restore --staged <fitxer>...» per a fer «unstage»)" +#: wt-status.c #, c-format msgid " (use \"git restore --source=%s --staged <file>...\" to unstage)" msgstr "" " (useu «git restore --source=%s --staged <fitxer>...» per a fer «unstage»)" +#: wt-status.c msgid " (use \"git rm --cached <file>...\" to unstage)" msgstr " (useu «git rm --cached <fitxer>...» per a fer «unstage»)" +#: wt-status.c msgid " (use \"git add <file>...\" to mark resolution)" msgstr " (useu «git add <fitxer>...» per a senyalar resolució)" +#: wt-status.c msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)" msgstr "" " (useu «git add/rm <fitxer>...» segons sigui apropiat per a senyalar " "resolució)" +#: wt-status.c msgid " (use \"git rm <file>...\" to mark resolution)" msgstr " (useu «git rm <fitxer>...» per a senyalar resolució)" +#: wt-status.c msgid "Changes to be committed:" msgstr "Canvis a cometre:" +#: wt-status.c msgid "Changes not staged for commit:" msgstr "Canvis no «staged» per a cometre:" +#: wt-status.c msgid " (use \"git add <file>...\" to update what will be committed)" msgstr " (useu «git add <fitxer>...» per a actualitzar què es cometrà )" +#: wt-status.c msgid " (use \"git add/rm <file>...\" to update what will be committed)" msgstr " (useu «git add/rm <fitxer>...» per a actualitzar què es cometrà )" +#: wt-status.c msgid "" " (use \"git restore <file>...\" to discard changes in working directory)" msgstr "" " (useu «git restore <fitxer>...» per a descartar canvis en el directori de " "treball)" +#: wt-status.c msgid " (commit or discard the untracked or modified content in submodules)" msgstr "" " (cometeu o descarteu el contingut modificat o no seguit en els submòduls)" +#: wt-status.c #, c-format msgid " (use \"git %s <file>...\" to include in what will be committed)" msgstr " (useu «git %s <fitxer>...» per a incloure'ls en la comissió)" +#: wt-status.c msgid "both deleted:" msgstr "suprimit per ambdós:" +#: wt-status.c msgid "added by us:" msgstr "afegit per nosaltres:" +#: wt-status.c msgid "deleted by them:" msgstr "suprimit per ells:" +#: wt-status.c msgid "added by them:" msgstr "afegit per ells:" +#: wt-status.c msgid "deleted by us:" msgstr "suprimit per nosaltres:" +#: wt-status.c msgid "both added:" msgstr "afegit per ambdós:" +#: wt-status.c msgid "both modified:" msgstr "modificat per ambdós:" +#: wt-status.c msgid "new file:" msgstr "fitxer nou:" +#: wt-status.c msgid "copied:" msgstr "copiat:" +#: wt-status.c msgid "deleted:" msgstr "suprimit:" +#: wt-status.c msgid "modified:" msgstr "modificat:" +#: wt-status.c msgid "renamed:" msgstr "canviat de nom:" +#: wt-status.c msgid "typechange:" msgstr "canviat de tipus:" +#: wt-status.c msgid "unknown:" msgstr "desconegut:" +#: wt-status.c msgid "unmerged:" msgstr "sense fusionar:" +#: wt-status.c msgid "new commits, " msgstr "comissions noves, " +#: wt-status.c msgid "modified content, " msgstr "contingut modificat, " +#: wt-status.c msgid "untracked content, " msgstr "contingut no seguit, " +#: wt-status.c #, c-format msgid "Your stash currently has %d entry" msgid_plural "Your stash currently has %d entries" msgstr[0] "L'«stash» té actualment %d entrada" msgstr[1] "L'«stash» té actualment %d entrades" +#: wt-status.c msgid "Submodules changed but not updated:" msgstr "Submòduls canviats però no actualitzats:" +#: wt-status.c msgid "Submodule changes to be committed:" msgstr "Canvis de submòdul a cometre:" +#: wt-status.c msgid "" "Do not modify or remove the line above.\n" "Everything below it will be ignored." @@ -22395,6 +28793,7 @@ msgstr "" "No modifiqueu ni elimineu la lÃnia de dalt.\n" "Tot el que hi ha a sota s'ignorarà ." +#: wt-status.c #, c-format msgid "" "\n" @@ -22406,90 +28805,115 @@ msgstr "" "darrere.\n" "Podeu utilitzar «--no-ahead-behind» per a evitar-ho.\n" +#: wt-status.c msgid "You have unmerged paths." msgstr "Teniu camins sense fusionar." +#: wt-status.c msgid " (fix conflicts and run \"git commit\")" msgstr " (arregleu els conflictes i executeu «git commit»)" +#: wt-status.c msgid " (use \"git merge --abort\" to abort the merge)" msgstr " (useu «git merge --abort» per a avortar la fusió)" +#: wt-status.c msgid "All conflicts fixed but you are still merging." msgstr "Tots els conflictes estan arreglats però encara esteu fusionant." +#: wt-status.c msgid " (use \"git commit\" to conclude merge)" msgstr " (useu «git commit» per a concloure la fusió)" +#: wt-status.c msgid "You are in the middle of an am session." msgstr "Esteu enmig d'una sessió am." +#: wt-status.c msgid "The current patch is empty." msgstr "El pedaç actual està buit." +#: wt-status.c msgid " (fix conflicts and then run \"git am --continue\")" msgstr " (arregleu els conflictes i després executeu «git am --continue»)" +#: wt-status.c msgid " (use \"git am --skip\" to skip this patch)" msgstr " (useu «git am --skip» per a ometre aquest pedaç)" +#: wt-status.c msgid "" " (use \"git am --allow-empty\" to record this patch as an empty commit)" msgstr "" " (useu «git am --allow-empty» per a enregistrar aquest pedaç com una " "comissió buida)" +#: wt-status.c msgid " (use \"git am --abort\" to restore the original branch)" msgstr " (useu «git am --abort» per a restaurar la branca original)" +#: wt-status.c msgid "git-rebase-todo is missing." msgstr "Manca git-rebase-todo." +#: wt-status.c msgid "No commands done." msgstr "No s'ha fet cap ordre." +#: wt-status.c #, c-format msgid "Last command done (%<PRIuMAX> command done):" msgid_plural "Last commands done (%<PRIuMAX> commands done):" msgstr[0] "Darrera ordre acabada (%<PRIuMAX> ordre acabada):" msgstr[1] "Darreres ordres acabades (%<PRIuMAX> ordres acabades):" +#: wt-status.c #, c-format msgid " (see more in file %s)" msgstr " (vegeu més en el fitxer %s)" +#: wt-status.c msgid "No commands remaining." msgstr "No manca cap ordre." +#: wt-status.c #, c-format msgid "Next command to do (%<PRIuMAX> remaining command):" msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):" msgstr[0] "Següent ordre a fer (%<PRIuMAX> ordre restant):" msgstr[1] "Següents ordres a fer (%<PRIuMAX> ordres restants):" +#: wt-status.c msgid " (use \"git rebase --edit-todo\" to view and edit)" msgstr " (useu «git rebase --edit-todo» per a veure i editar)" +#: wt-status.c #, c-format msgid "You are currently rebasing branch '%s' on '%s'." msgstr "Actualment esteu fent «rebase» de la branca «%s» en «%s»." +#: wt-status.c msgid "You are currently rebasing." msgstr "Actualment esteu fent «rebase»." +#: wt-status.c msgid " (fix conflicts and then run \"git rebase --continue\")" msgstr " (arregleu els conflictes i després executeu «git rebase --continue»)" +#: wt-status.c msgid " (use \"git rebase --skip\" to skip this patch)" msgstr " (useu «git rebase --skip» per a ometre aquest pedaç)" +#: wt-status.c msgid " (use \"git rebase --abort\" to check out the original branch)" msgstr " (useu «git rebase --abort» per a agafar la branca original)" +#: wt-status.c msgid " (all conflicts fixed: run \"git rebase --continue\")" msgstr "" " (tots els conflictes estan arreglats: executeu «git rebase --continue»)" +#: wt-status.c #, c-format msgid "" "You are currently splitting a commit while rebasing branch '%s' on '%s'." @@ -22497,128 +28921,164 @@ msgstr "" "Actualment esteu dividint una comissió mentre es fa «rebase» de la branca " "«%s» en «%s»." +#: wt-status.c msgid "You are currently splitting a commit during a rebase." msgstr "Actualment esteu dividint una comissió durant un «rebase»." +#: wt-status.c msgid " (Once your working directory is clean, run \"git rebase --continue\")" msgstr "" " (Una vegada que el vostre directori de treball sigui net, executeu «git " "rebase --continue»)" +#: wt-status.c #, c-format msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." msgstr "" "Actualment esteu editant una comissió mentre es fa «rebase» de la branca " "«%s» en «%s»." +#: wt-status.c msgid "You are currently editing a commit during a rebase." msgstr "Actualment esteu editant una comissió durant un «rebase»." +#: wt-status.c msgid " (use \"git commit --amend\" to amend the current commit)" msgstr " (useu «git commit --amend» per a esmenar la comissió actual)" +#: wt-status.c msgid "" " (use \"git rebase --continue\" once you are satisfied with your changes)" msgstr "" " (useu «git rebase --continue» una vegada que estigueu satisfet amb els " "vostres canvis)" +#: wt-status.c msgid "Cherry-pick currently in progress." msgstr "Hi ha «cherry pick» actualment en curs." +#: wt-status.c #, c-format msgid "You are currently cherry-picking commit %s." msgstr "Actualment esteu fent «cherry pick» a la comissió %s." +#: wt-status.c msgid " (fix conflicts and run \"git cherry-pick --continue\")" msgstr " (arregleu els conflictes i executeu «git cherry-pick --continue»)" +#: wt-status.c msgid " (run \"git cherry-pick --continue\" to continue)" msgstr " (executeu «git cherry-pick --continue» per a continuar)" +#: wt-status.c msgid " (all conflicts fixed: run \"git cherry-pick --continue\")" msgstr "" " (tots els conflictes estan arreglats: executeu «git cherry-pick --" "continue»)" +#: wt-status.c msgid " (use \"git cherry-pick --skip\" to skip this patch)" msgstr " (useu «git cherry-pick --skip» per a ometre aquest pedaç)" +#: wt-status.c msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)" msgstr "" " (useu «git cherry-pick --abort» per a cancel·lar l'operació de «cherry " "pick»)" +#: wt-status.c msgid "Revert currently in progress." msgstr "Una reversió està actualment en curs." +#: wt-status.c #, c-format msgid "You are currently reverting commit %s." msgstr "Actualment esteu revertint la comissió %s." +#: wt-status.c msgid " (fix conflicts and run \"git revert --continue\")" msgstr " (arregleu els conflictes i executeu «git revert --continue»)" +#: wt-status.c msgid " (run \"git revert --continue\" to continue)" msgstr " (executeu «git revert --continue» per a continuar)" +#: wt-status.c msgid " (all conflicts fixed: run \"git revert --continue\")" msgstr "" " (tots els conflictes estan arreglats: executeu «git revert --continue»)" +#: wt-status.c msgid " (use \"git revert --skip\" to skip this patch)" msgstr " (useu «git revert --skip» per a ometre aquest pedaç)" +#: wt-status.c msgid " (use \"git revert --abort\" to cancel the revert operation)" msgstr " (useu «git revert --abort» per a cancel·lar l'operació de reversió)" +#: wt-status.c #, c-format msgid "You are currently bisecting, started from branch '%s'." msgstr "Actualment esteu bisecant, heu començat des de la branca «%s»." +#: wt-status.c msgid "You are currently bisecting." msgstr "Actualment esteu bisecant." +#: wt-status.c msgid " (use \"git bisect reset\" to get back to the original branch)" msgstr " (useu «git bisect reset» per a tornar a la branca original)" +#: wt-status.c msgid "You are in a sparse checkout." msgstr "Esteu en un «sparse-checkout»." +#: wt-status.c #, c-format msgid "You are in a sparse checkout with %d%% of tracked files present." msgstr "Esteu en un «sparse-checkout» amb un %d%% de fitxers seguits presents." +#: wt-status.c msgid "On branch " msgstr "En la branca " +#: wt-status.c msgid "interactive rebase in progress; onto " msgstr "«rebase» interactiu en curs; sobre " +#: wt-status.c msgid "rebase in progress; onto " msgstr "«rebase» en curs; sobre " +#: wt-status.c msgid "HEAD detached at " msgstr "HEAD separat a " +#: wt-status.c msgid "HEAD detached from " msgstr "HEAD separat des de " +#: wt-status.c msgid "Not currently on any branch." msgstr "Actualment no s'és en cap branca." +#: wt-status.c msgid "Initial commit" msgstr "Comissió inicial" +#: wt-status.c msgid "No commits yet" msgstr "No s'ha fet cap comissió encara" +#: wt-status.c msgid "Untracked files" msgstr "Fitxers no seguits" +#: wt-status.c msgid "Ignored files" msgstr "Fitxers ignorats" +#: wt-status.c #, c-format msgid "" "It took %.2f seconds to enumerate untracked files,\n" @@ -22628,32 +29088,40 @@ msgstr "" "però els resultats es van emmagatzemar a la memòria cau, i les\n" "execucions posteriors podrien ser més rà pides." +#: wt-status.c #, c-format msgid "It took %.2f seconds to enumerate untracked files." msgstr "S'han trigat %.2f segons a enumerar els fitxers sense seguiment." +#: wt-status.c msgid "See 'git help status' for information on how to improve this." msgstr "" "Vegeu «git help status» per a obtenir informació sobre com millorar-ho." +#: wt-status.c #, c-format msgid "Untracked files not listed%s" msgstr "Els fitxers no seguits no estan llistats%s" +#: wt-status.c msgid " (use -u option to show untracked files)" msgstr " (useu l'opció -u per a mostrar els fitxers no seguits)" +#: wt-status.c msgid "No changes" msgstr "Sense canvis" +#: wt-status.c #, c-format msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" msgstr "no hi ha canvis afegits a cometre (useu «git add» o «git commit -a»)\n" +#: wt-status.c #, c-format msgid "no changes added to commit\n" msgstr "no hi ha canvis afegits a cometre\n" +#: wt-status.c #, c-format msgid "" "nothing added to commit but untracked files present (use \"git add\" to " @@ -22662,60 +29130,75 @@ msgstr "" "no hi ha res afegit a cometre però hi ha fitxers no seguits (useu «git add» " "per a seguir-los)\n" +#: wt-status.c #, c-format msgid "nothing added to commit but untracked files present\n" msgstr "no hi ha res afegit a cometre però hi ha fitxers no seguits\n" +#: wt-status.c #, c-format msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" msgstr "" "no hi ha res a cometre (creeu/copieu fitxers i useu «git add» per a seguir-" "los)\n" +#: wt-status.c #, c-format msgid "nothing to commit\n" msgstr "no hi ha res a cometre\n" +#: wt-status.c #, c-format msgid "nothing to commit (use -u to show untracked files)\n" msgstr "" "no hi ha res a cometre (useu -u per a mostrar els fitxers no seguits)\n" +#: wt-status.c #, c-format msgid "nothing to commit, working tree clean\n" msgstr "no hi ha res a cometre, l'arbre de treball està net\n" +#: wt-status.c msgid "No commits yet on " msgstr "No s'ha fet cap comissió encara a " +#: wt-status.c msgid "HEAD (no branch)" msgstr "HEAD (sense branca)" +#: wt-status.c msgid "different" msgstr "diferent" +#: wt-status.c msgid "behind " msgstr "darrere " +#: wt-status.c msgid "ahead " msgstr "davant per " #. TRANSLATORS: the action is e.g. "pull with rebase" +#: wt-status.c #, c-format msgid "cannot %s: You have unstaged changes." msgstr "no es pot %s: Teniu canvis «unstaged»." +#: wt-status.c msgid "additionally, your index contains uncommitted changes." msgstr "addicionalment, el vostre Ãndex conté canvis sense cometre." +#: wt-status.c #, c-format msgid "cannot %s: Your index contains uncommitted changes." msgstr "no es pot %s: El vostre Ãndex conté canvis sense cometre." +#: xdiff-interface.c #, c-format msgid "unknown style '%s' given for '%s'" msgstr "estil desconegut «%s» donat per a «%s»" +#: git-merge-octopus.sh git-merge-resolve.sh msgid "" "Error: Your local changes to the following files would be overwritten by " "merge" @@ -22723,92 +29206,120 @@ msgstr "" "Error: Els vostres canvis locals als fitxers següents se sobreescriurien per " "a fusionar" +#: git-merge-octopus.sh msgid "Automated merge did not work." msgstr "La fusió automà tica no ha funcionat." +#: git-merge-octopus.sh msgid "Should not be doing an octopus." msgstr "No s'ha de fer un «octopus»." +#: git-merge-octopus.sh #, sh-format msgid "Unable to find common commit with $pretty_name" msgstr "No s'ha pogut trobar cap comissió en comú amb $pretty_name" +#: git-merge-octopus.sh #, sh-format msgid "Already up to date with $pretty_name" msgstr "Ja està al dia amb $pretty_name" +#: git-merge-octopus.sh #, sh-format msgid "Fast-forwarding to: $pretty_name" msgstr "S'està avançant rà pidament a: $pretty_name" +#: git-merge-octopus.sh #, sh-format msgid "Trying simple merge with $pretty_name" msgstr "S'està intentant una fusió simple amb $pretty_name" +#: git-merge-octopus.sh msgid "Simple merge did not work, trying automatic merge." msgstr "" "La fusió simple no ha funcionat, s'està intentant una fusió automà tica." +#: git-sh-setup.sh #, sh-format msgid "usage: $dashless $USAGE" msgstr "ús: $dashless $USAGE" +#: git-sh-setup.sh #, sh-format msgid "Cannot chdir to $cdup, the toplevel of the working tree" msgstr "" "No es pot canviar de directori a $cdup, el nivell superior de l'arbre de " "treball" +#: git-sh-setup.sh #, sh-format msgid "fatal: $program_name cannot be used without a working tree." msgstr "fatal: no es pot usar $program_name sense un arbre de treball." +#: git-sh-setup.sh msgid "Cannot rewrite branches: You have unstaged changes." msgstr "No es poden reescriure branques: Teniu canvis «unstaged»." +#: git-sh-setup.sh #, sh-format msgid "Cannot $action: You have unstaged changes." msgstr "No es pot $action: Teniu canvis «unstaged»." +#: git-sh-setup.sh #, sh-format msgid "Cannot $action: Your index contains uncommitted changes." msgstr "No es pot $action: El vostre Ãndex conté canvis sense cometre." +#: git-sh-setup.sh msgid "Additionally, your index contains uncommitted changes." msgstr "Addicionalment, el vostre Ãndex conté canvis sense cometre." +#: git-sh-setup.sh msgid "You need to run this command from the toplevel of the working tree." msgstr "" "Heu d'executar aquesta ordre des del nivell superior de l'arbre de treball." +#: git-sh-setup.sh msgid "Unable to determine absolute path of git directory" msgstr "No s'ha pogut determinar el camà absolut del directori de git" +#: git-send-email.perl msgid "local zone differs from GMT by a non-minute interval\n" msgstr "la zona local difereix de GMT per un interval que no és de minuts\n" +#: git-send-email.perl msgid "local time offset greater than or equal to 24 hours\n" msgstr "el desplaçament de la zona local és més gran o igual a 24 hores\n" +#: git-send-email.perl #, perl-format msgid "fatal: command '%s' died with exit code %d" msgstr "fatal: l'ordre «%s» ha mort amb el codi de sortida %d" +#: git-send-email.perl msgid "the editor exited uncleanly, aborting everything" msgstr "l'editor no ha sortit correctament, avortant-ho tot" +#: git-send-email.perl #, perl-format msgid "" "'%s' contains an intermediate version of the email you were composing.\n" msgstr "«%s» conté una versió intermèdia del correu que està veu redactant.\n" +#: git-send-email.perl #, perl-format msgid "'%s.final' contains the composed email.\n" msgstr "«%s.final» conté el correu redactat.\n" +#: git-send-email.perl msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases és incompatible amb altres opcions\n" +#: git-send-email.perl +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases i --translate-aliases s'exclouen mútuament\n" + +#: git-send-email.perl msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -22819,9 +29330,11 @@ msgstr "" "la «e». Establiu sendemail.forbidSendmailVariables a false per a desactivar\n" "la comprovació.\n" +#: git-send-email.perl msgid "Cannot run git format-patch from outside a repository\n" msgstr "No es pot executar git format-patch des de fora del repositori\n" +#: git-send-email.perl msgid "" "`batch-size` and `relogin` must be specified together (via command-line or " "configuration option)\n" @@ -22829,30 +29342,37 @@ msgstr "" "«batch-size» i «relogin» s'han d'especificar junts (a través de la lÃnia " "d'ordres o l'opció de configuració)\n" +#: git-send-email.perl #, perl-format msgid "Unknown --suppress-cc field: '%s'\n" msgstr "Camp --suppress-cc desconegut: «%s»\n" +#: git-send-email.perl #, perl-format msgid "Unknown --confirm setting: '%s'\n" msgstr "Parà metre --confirm desconegut: «%s»\n" +#: git-send-email.perl #, perl-format msgid "warning: sendmail alias with quotes is not supported: %s\n" msgstr "avÃs: no s'admet l'à lies de sendmail amb cometes: %s\n" +#: git-send-email.perl #, perl-format msgid "warning: `:include:` not supported: %s\n" msgstr "avÃs: «:include:» no s'admet: %s\n" +#: git-send-email.perl #, perl-format msgid "warning: `/file` or `|pipe` redirection not supported: %s\n" msgstr "avÃs: les redireccions «/file» ni «|pipe» no s'admeten: %s\n" +#: git-send-email.perl #, perl-format msgid "warning: sendmail line is not recognized: %s\n" msgstr "avÃs: no es pot reconèixer la lÃnia sendmail: %s\n" +#: git-send-email.perl #, perl-format msgid "" "File '%s' exists but it could also be the range of commits\n" @@ -22867,10 +29387,12 @@ msgstr "" " * Dient «./%s» si volÃeu especificar un fitxer; o\n" " * Proporcionant l'opció «--format-patch» si volÃeu especificar un rang.\n" +#: git-send-email.perl #, perl-format msgid "Failed to opendir %s: %s" msgstr "S'ha produït un error en obrir el directori %s: %s" +#: git-send-email.perl msgid "" "\n" "No patch files specified!\n" @@ -22880,14 +29402,17 @@ msgstr "" "No s'han especificat fitxers de pedaç\n" "\n" +#: git-send-email.perl #, perl-format msgid "No subject line in %s?" msgstr "Sense assumpte a %s?" +#: git-send-email.perl #, perl-format msgid "Failed to open for writing %s: %s" msgstr "S'ha produït un error en obrir per escriptura %s: %s" +#: git-send-email.perl msgid "" "Lines beginning in \"GIT:\" will be removed.\n" "Consider including an overall diffstat or table of contents\n" @@ -22901,22 +29426,27 @@ msgstr "" "\n" "Esborreu el contingut del cos si no voleu enviar cap resum.\n" +#: git-send-email.perl #, perl-format msgid "Failed to open %s.final: %s" msgstr "S'ha produït un error en obrir %s.final: %s" +#: git-send-email.perl #, perl-format msgid "Failed to open %s: %s" msgstr "S'ha produït un error en obrir %s: %s" +#: git-send-email.perl msgid "Summary email is empty, skipping it\n" msgstr "El correu electrònic de resum està buit, s'omet\n" #. TRANSLATORS: please keep [y/N] as is. +#: git-send-email.perl #, perl-format msgid "Are you sure you want to use <%s> [y/N]? " msgstr "Esteu segur que voleu usar <%s> [y/N]? " +#: git-send-email.perl msgid "" "The following files are 8bit, but do not declare a Content-Transfer-" "Encoding.\n" @@ -22924,9 +29454,11 @@ msgstr "" "Els fitxers següents són 8bit, però no declaren un Content-Transfer-" "Encoding.\n" +#: git-send-email.perl msgid "Which 8bit encoding should I declare [UTF-8]? " msgstr "Quina codificació de 8 bits hauria de declarar [UTF-8]? " +#: git-send-email.perl #, perl-format msgid "" "Refusing to send because the patch\n" @@ -22939,19 +29471,23 @@ msgstr "" "perquè la plantilla té l'assumpte «*** SUBJECT HERE ***». Passeu --force si " "realment voleu enviar-ho.\n" +#: git-send-email.perl msgid "To whom should the emails be sent (if anyone)?" msgstr "" "A qui s'haurien d'enviar els correus electrònics (si s'han d'enviar a algú)?" +#: git-send-email.perl #, perl-format msgid "fatal: alias '%s' expands to itself\n" msgstr "fatal: l'à lies «%s» s'expandeix a si mateix\n" +#: git-send-email.perl msgid "Message-ID to be used as In-Reply-To for the first email (if any)? " msgstr "" "S'ha d'usar el Message-ID com a In-Reply-To pel primer correu (si n'hi ha " "cap)? " +#: git-send-email.perl #, perl-format msgid "error: unable to extract a valid address from: %s\n" msgstr "error: no s'ha pogut extreure una adreça và lida de: %s\n" @@ -22959,13 +29495,16 @@ msgstr "error: no s'ha pogut extreure una adreça và lida de: %s\n" #. TRANSLATORS: Make sure to include [q] [d] [e] in your #. translation. The program will only accept English input #. at this point. +#: git-send-email.perl msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): " msgstr "Què cal fer amb aquesta adreça? ([q]surt|[d]escarta|[e]dita): " +#: git-send-email.perl #, perl-format msgid "CA path \"%s\" does not exist" msgstr "el camà CA «%s» no existeix" +#: git-send-email.perl msgid "" " The Cc list above has been expanded by additional\n" " addresses found in the patch commit message. By default\n" @@ -22992,95 +29531,121 @@ msgstr "" #. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your #. translation. The program will only accept English input #. at this point. +#: git-send-email.perl msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): " msgstr "" "Voleu enviar aquest correu electrònic? ([y]sÃ|[n]o|[e]dita|[q]surt|[a]tot): " +#: git-send-email.perl msgid "Send this email reply required" msgstr "Requereix resposta en enviar el correu" +#: git-send-email.perl msgid "The required SMTP server is not properly defined." msgstr "El servidor SMTP requerit no està correctament definit." +#: git-send-email.perl #, perl-format msgid "Server does not support STARTTLS! %s" msgstr "El servidor no admet STARTTLS! %s" +#: git-send-email.perl #, perl-format msgid "STARTTLS failed! %s" msgstr "STARTTLS ha fallat! %s" +#: git-send-email.perl msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug." msgstr "" "No s'ha pogut inicialitzar SMTP correctament. Comproveu-ho la configuració i " "useu --smtp-debug." +#: git-send-email.perl #, perl-format msgid "Failed to send %s\n" msgstr "S'ha produït un error en enviar %s\n" +#: git-send-email.perl #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Simulació d'enviament %s\n" +msgid "Dry-Sent %s" +msgstr "Prova-Enviat %s" +#: git-send-email.perl #, perl-format -msgid "Sent %s\n" -msgstr "Enviat %s\n" +msgid "Sent %s" +msgstr "Enviat %s" -msgid "Dry-OK. Log says:\n" -msgstr "Simulació de correcte. El registre diu:\n" +#: git-send-email.perl +msgid "Dry-OK. Log says:" +msgstr "Prova correcta. El registre diu:" -msgid "OK. Log says:\n" -msgstr "Correcte. El registre diu: \n" +#: git-send-email.perl +msgid "OK. Log says:" +msgstr "Correcte. El registre diu:" +#: git-send-email.perl msgid "Result: " msgstr "Resultat: " -msgid "Result: OK\n" -msgstr "Resultat: correcte\n" +# OK = correcte? +#: git-send-email.perl +msgid "Result: OK" +msgstr "Resultat: correcte" +#: git-send-email.perl #, perl-format msgid "can't open file %s" msgstr "no es pot obrir el fitxer %s" +#: git-send-email.perl #, perl-format msgid "(mbox) Adding cc: %s from line '%s'\n" msgstr "(mbox) S'està afegint cc: %s des de la lÃnia «%s»\n" +#: git-send-email.perl #, perl-format msgid "(mbox) Adding to: %s from line '%s'\n" msgstr "(mbox) S'està afegint a: %s des de la lÃnia «%s»\n" +#: git-send-email.perl #, perl-format msgid "(non-mbox) Adding cc: %s from line '%s'\n" msgstr "(no mbox) S'està afegint cc: %s des de la lÃnia «%s»\n" +#: git-send-email.perl #, perl-format msgid "(body) Adding cc: %s from line '%s'\n" msgstr "(cos) S'està afegint cc: %s des de la lÃnia «%s»\n" +#: git-send-email.perl #, perl-format msgid "(%s) Could not execute '%s'" msgstr "(%s) no s'ha pogut executar «%s»" +#: git-send-email.perl #, perl-format msgid "(%s) Malformed output from '%s'" msgstr "(%s) Sortida mal formada de «%s»" +#: git-send-email.perl #, perl-format msgid "(%s) failed to close pipe to '%s'" msgstr "(%s) s'ha produït un error en tancar el conducte «%s»" +#: git-send-email.perl #, perl-format msgid "(%s) Adding %s: %s from: '%s'\n" msgstr "(%s) S'està afegint %s: %s des de: «%s»\n" +#: git-send-email.perl msgid "cannot send message as 7bit" msgstr "no es pot enviar el missatge en 7 bits" +#: git-send-email.perl msgid "invalid transfer encoding" msgstr "codificació de transferència no và lida" +#: git-send-email.perl #, perl-format msgid "" "fatal: %s: rejected by %s hook\n" @@ -23091,10 +29656,12 @@ msgstr "" "%s\n" "avÃs: no s'ha enviat cap pedaç\n" +#: git-send-email.perl #, perl-format msgid "unable to open %s: %s\n" msgstr "no s'ha pogut obrir %s: %s\n" +#: git-send-email.perl #, perl-format msgid "" "fatal: %s:%d is longer than 998 characters\n" @@ -23103,11 +29670,91 @@ msgstr "" "fatal: %s:%d té més de 998 carà cters\n" "avÃs: no s'ha enviat cap pedaç\n" +#: git-send-email.perl #, perl-format msgid "Skipping %s with backup suffix '%s'.\n" msgstr "S'està ometent %s amb el sufix de còpia de seguretat «%s».\n" #. TRANSLATORS: please keep "[y|N]" as is. +#: git-send-email.perl #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Esteu segur que voleu enviar %s? [y|N]: " + +#~ msgid "revision walk setup failed\n" +#~ msgstr "la configuració del recorregut de revisions ha fallat\n" + +#, c-format +#~ msgid "unable to parse contact: %s" +#~ msgstr "no s'ha pogut analitzar el contacte: %s" + +#, c-format +#~ msgid "truncating .rej filename to %.*s.rej" +#~ msgstr "s'està truncant el nom del fitxer .rej a %.*s.rej" + +#~ msgid "" +#~ "the add.interactive.useBuiltin setting has been removed!\n" +#~ "See its entry in 'git help config' for details." +#~ msgstr "" +#~ "s'ha eliminat la configuració add.interactive.useBuiltin\n" +#~ "Per a més detalls, vegeu la seva entrada a «git help config»." + +#~ msgid "" +#~ "Use -f if you really want to add them.\n" +#~ "Turn this message off by running\n" +#~ "\"git config advice.addIgnoredFile false\"" +#~ msgstr "" +#~ "Utilitzeu -f si realment voleu afegir-los.\n" +#~ "Desactiveu aquest missatge executant\n" +#~ "«git config advice.addIgnoredFile false»" + +#~ msgid "" +#~ "Maybe you wanted to say 'git add .'?\n" +#~ "Turn this message off by running\n" +#~ "\"git config advice.addEmptyPathspec false\"" +#~ msgstr "" +#~ "Potser voleu dir «git add .»?\n" +#~ "Desactiveu aquest missatge executant\n" +#~ "«git config advice.addEmptyPathspec false»" + +#~ msgid "git archive: Remote with no URL" +#~ msgstr "git archive: Remot sense URL" + +#~ msgid "" +#~ "clean.requireForce defaults to true and neither -i, -n, nor -f given; " +#~ "refusing to clean" +#~ msgstr "" +#~ "clean.requireForce és per defecte cert i ni -i, -n ni -f s'han indicat; " +#~ "refusant netejar" + +#~ msgid "only one action at a time" +#~ msgstr "només una acció cada cop" + +#~ msgid "use [RFC PATCH] instead of [PATCH]" +#~ msgstr "useu [RFC PATCH] en comptes de [PATCH]" + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not start with '('" +#~ msgstr "format incorrecte del ls-files: l'element «%s» no comença amb «(»" + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not end in ')'" +#~ msgstr "format incorrecte del ls-files: l'element «%s» no acaba amb «)»" + +#, c-format +#~ msgid "bad ls-files format: %%%.*s" +#~ msgstr "format incorrecte de ls-files: %%%.*s" + +#, c-format +#~ msgid "no URLs configured for remote '%s'" +#~ msgstr "cap URL configurat per al remot «%s»" + +#~ msgid "keep redundant, empty commits" +#~ msgstr "retén les comissions redundants i buides" + +#~ msgid "core.commentChar should only be one ASCII character" +#~ msgstr "core.commentChar només hauria de ser un carà cter ASCII" + +#, c-format +#~ msgid "remote '%s' has no configured URL" +#~ msgstr "el remot «%s» no té cap URL configurat" @@ -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-04-26 16:16+0200\n" -"PO-Revision-Date: 2024-04-26 16:22+0200\n" +"POT-Creation-Date: 2024-10-05 16:17+0200\n" +"PO-Revision-Date: 2024-10-05 16:18+0200\n" "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n" "Language-Team: German\n" "Language: de\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -"X-Generator: Poedit 3.4.1\n" +"X-Generator: Poedit 3.4.4\n" #, c-format msgid "Huh (%s)?" @@ -566,7 +566,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - diesen Patch-Block unbestimmt lassen, nächsten unbestimmten Patch-Block " @@ -579,9 +579,13 @@ msgstr "" "/ - nach Patch-Block suchen, der regulärem Ausdruck entspricht\n" "s - aktuellen Patch-Block in kleinere Patch-Blöcke aufteilen\n" "e - aktuellen Patch-Block manuell editieren\n" -"p - aktuellen Patch-Block anzeigen\n" +"p - aktuellen Patch-Block anzeigen, 'P' um Anzeigeprogramm zu benutzen\n" "? - Hilfe anzeigen\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Es wird nur ein Buchstabe erwartet, '%s' erhalten" + msgid "No previous hunk" msgstr "Kein vorheriger Patch-Block" @@ -630,9 +634,19 @@ msgstr "In %d Patch-Block aufgeteilt." msgid "Sorry, cannot edit this hunk" msgstr "Entschuldigung, kann diesen Patch-Block nicht bearbeiten" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Unbekannter Befehl '%s' (für Hilfe '?' verwenden)" + msgid "'git apply' failed" msgstr "'git apply' schlug fehl" +msgid "No changes." +msgstr "Keine Änderungen." + +msgid "Only binary files changed." +msgstr "Nur Binärdateien geändert." + #, c-format msgid "" "\n" @@ -1266,6 +1280,15 @@ msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "" "versuche 3-Wege-Merge, weiche auf normalen Patch aus, wenn dies fehlschlägt" +msgid "for conflicts, use our version" +msgstr "bei Konflikten unsere Variante verwenden" + +msgid "for conflicts, use their version" +msgstr "bei Konflikten ihre Variante verwenden" + +msgid "for conflicts, use a union version" +msgstr "bei Konflikten eine gemeinsame Variante verwenden" + msgid "build a temporary index based on embedded index information" msgstr "" "einen temporären Index, basierend auf den integrierten Index-Informationen, " @@ -1315,6 +1338,9 @@ msgstr "<Wurzelverzeichnis> vor alle Dateinamen stellen" msgid "don't return error for empty patches" msgstr "keinen Fehler für leere Patches zurückgeben" +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs, und --union erfordern --3way" + #, c-format msgid "cannot stream blob %s" msgstr "kann Blob %s nicht streamen" @@ -1388,6 +1414,10 @@ msgid "not a tree object: %s" msgstr "Kein Tree-Objekt: %s" #, c-format +msgid "failed to unpack tree object %s" +msgstr "Tree-Objekt %s konnte nicht entpackt werden" + +#, c-format msgid "File not found: %s" msgstr "Datei nicht gefunden: %s" @@ -1517,6 +1547,10 @@ msgstr "ignoriere übermäßig große gitattributes-Datei '%s'" msgid "ignoring overly large gitattributes blob '%s'" msgstr "ignoriere übermäßig großen gitattribute-Blob '%s'" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "" +"kann nicht --attr-source oder GIT_ATTR_SOURCE ohne Repository verwenden" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "ungültiges --attr-source oder GIT_ATTR_SOURCE" @@ -1838,13 +1872,6 @@ msgid "Unstaged changes after refreshing the index:" msgstr "" "Nicht zum Commit vorgemerkte Änderungen nach Aktualisierung der Staging-Area:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"Die Einstellung add.interactive.useBuiltin wurde entfernt!\n" -"Siehe den Eintrag in 'git help config' für Details." - msgid "could not read the index" msgstr "konnte den Index nicht lesen" @@ -2302,6 +2329,9 @@ msgstr "Patch-Operation abbrechen, aber HEAD an aktueller Stelle belassen" msgid "show the patch being applied" msgstr "den Patch, der gerade angewendet wird, anzeigen" +msgid "try to apply current patch again" +msgstr "den aktuellen Patch erneut versuchen anzuwenden" + msgid "record the empty patch as an empty commit" msgstr "leerer Patch als leeren Commit gespeichert" @@ -2357,9 +2387,6 @@ msgstr "git apply [<Optionen>] [<Patch>...]" msgid "could not redirect output" msgstr "konnte Ausgabe nicht umleiten" -msgid "git archive: Remote with no URL" -msgstr "git archive: Externes Archiv ohne URL" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: ACK/NAK erwartet, Flush-Paket bekommen" @@ -2514,9 +2541,6 @@ msgstr "" "Ungültiges Argument %s für 'git bisect terms'.\n" "Unterstützte Optionen sind: --term-good|--term-old und --term-bad|--term-new." -msgid "revision walk setup failed\n" -msgstr "Einrichtung des Revisionsgangs fehlgeschlagen\n" - #, c-format msgid "could not open '%s' for appending" msgstr "konnte '%s' nicht zum Anhängen öffnen" @@ -3282,6 +3306,9 @@ msgstr "Um ein Paket zu erstellen wird ein Repository benötigt." msgid "do not show bundle details" msgstr "Keine Bundle-Details anzeigen" +msgid "need a repository to verify a bundle" +msgstr "um ein Paket zu überprüfen wird ein Repository benötigt" + #, c-format msgid "%s is okay\n" msgstr "%s ist in Ordnung\n" @@ -3519,9 +3546,14 @@ msgstr "git check-mailmap [<Optionen>] <Kontakt>..." msgid "also read contacts from stdin" msgstr "ebenfalls Kontakte von der Standard-Eingabe lesen" -#, c-format -msgid "unable to parse contact: %s" -msgstr "konnte Kontakt nicht parsen: %s" +msgid "read additional mailmap entries from file" +msgstr "zusätzliche mailmap-Einträge aus Datei lesen" + +msgid "blob" +msgstr "Blob" + +msgid "read additional mailmap entries from blob" +msgstr "zusätzliche mailmap-Einträge aus Blob lesen" msgid "no contacts specified" msgstr "keine Kontakte angegeben" @@ -3884,6 +3916,10 @@ msgid "'%s' cannot be used with switching branches" msgstr "'%s' kann nicht beim Wechseln von Branches verwendet werden" #, c-format +msgid "'%s' needs the paths to check out" +msgstr "'%s' benötigt die Pfade zum Auschecken" + +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s' kann nicht mit '%s' verwendet werden" @@ -4324,6 +4360,14 @@ 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" @@ -4671,7 +4715,7 @@ msgstr "git commit-tree: Fehler beim Lesen" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4681,7 +4725,7 @@ msgid "" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<Modus>] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <Commit> | --fixup [(amend|" -"reword):]<Commit>)]\n" +"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" @@ -5180,15 +5224,60 @@ msgstr "" "voll und Ihr Kontingent nicht aufgebraucht ist und führen Sie\n" "anschließend \"git restore --staged :/\" zur Wiederherstellung aus." -msgid "git config [<options>]" -msgstr "git config [<Optionen>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<Datei-Option>] [<Anzeige-Option>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "nicht erkanntes --type Argument, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<Datei-Option>] [<Anzeige-Option>] [--includes] [--all] [--" +"regexp] [--value=<Wert>] [--fixed-value] [--default=<Standardwert>] " +"<Name>" -msgid "only one type at a time" -msgstr "nur ein Typ erlaubt" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<Datei-Option>] [--type=<Typ>] [--all] [--value=<Wert>] [--" +"fixed-value] <Name> <Wert>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<Datei-Option>] [--all] [--value=<Wert>] [--fixed-value] " +"<Name> <Wert>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<Datei-Option>] <alter-Name> <neuer-Name>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<Datei-Option>] <Name>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<Datei-Option>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "" +"git config [<Datei-Option>] --get-colorbool <Name> [<Standard-Ausgabe-ist-" +"Terminal>]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<Datei-Option>] [<Anzeige-Option>] [--includes] [--all] [--" +"regexp=<Regex>] [--value=<Wert>] [--fixed-value] [--default=<Standardwert>] " +"<Name>" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<Datei-Option>] [--type=<Typ>] [--comment=<Nachricht>] [--" +"all] [--value=<Wert>] [--fixed-value] <Name> <Wert>" msgid "Config file location" msgstr "Ort der Konfigurationsdatei" @@ -5214,55 +5303,6 @@ msgstr "Blob-Id" msgid "read config from given blob object" msgstr "Konfiguration von angegebenem Blob-Objekt lesen" -msgid "Action" -msgstr "Aktion" - -msgid "get value: name [value-pattern]" -msgstr "Wert zurückgeben: Name [Wert-Muster]" - -msgid "get all values: key [value-pattern]" -msgstr "alle Werte zurückgeben: Schlüssel [Wert-Muster]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "Werte für den regulären Ausdruck zurückgeben: Name-Regex [Wert-Muster]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "Wert spezifisch für eine URL zurückgeben: section[.var] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "alle passenden Variablen ersetzen: Name Wert [Wert-Muster] " - -msgid "add a new variable: name value" -msgstr "neue Variable hinzufügen: Name Wert" - -msgid "remove a variable: name [value-pattern]" -msgstr "eine Variable entfernen: Name [Wert-Muster]" - -msgid "remove all matches: name [value-pattern]" -msgstr "alle Übereinstimmungen entfernen: Name [Wert-Muster]" - -msgid "rename section: old-name new-name" -msgstr "eine Sektion umbenennen: alter-Name neuer-Name" - -msgid "remove a section: name" -msgstr "eine Sektion entfernen: Name" - -msgid "list all" -msgstr "alles auflisten" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "" -"nutze String-Gleichheit beim Vergleich von Werten mit dem 'Wert-Muster'" - -msgid "open an editor" -msgstr "einen Editor öffnen" - -msgid "find the color configured: slot [default]" -msgstr "die konfigurierte Farbe finden: Slot [Standard]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "die Farbeinstellung finden: Slot [Standard-Ausgabe-ist-Terminal]" - msgid "Type" msgstr "Typ" @@ -5290,8 +5330,8 @@ msgstr "Wert ist ein Pfad (Datei oder Verzeichnisname)" msgid "value is an expiry date" msgstr "Wert ist ein Verfallsdatum" -msgid "Other" -msgstr "Sonstiges" +msgid "Display options" +msgstr "Anzeigeoptionen" msgid "terminate values with NUL byte" msgstr "schließt Werte mit NUL-Byte ab" @@ -5299,9 +5339,6 @@ msgstr "schließt Werte mit NUL-Byte ab" msgid "show variable names only" msgstr "nur Variablennamen anzeigen" -msgid "respect include directives on lookup" -msgstr "beachtet \"include\"-Direktiven beim Nachschlagen" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "Ursprung der Konfiguration anzeigen (Datei, Standard-Eingabe, Blob, " @@ -5312,15 +5349,15 @@ msgstr "" "Zeige Geltungsbereich der Konfiguration (Arbeitsverzeichnis, lokal, global, " "systemweit, Befehl)" -msgid "value" -msgstr "Wert" +msgid "show config keys in addition to their values" +msgstr "Konfigurationsschlüssel zusätzlich zu dessen Werten anzeigen" -msgid "with --get, use default value when missing entry" -msgstr "mit --get, benutze den Standardwert, wenn der Eintrag fehlt" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "nicht erkanntes --type Argument, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "" -"menschenlesbare Kommentarzeichenfolge (# wird bei Bedarf vorangestellt)" +msgid "only one type at a time" +msgstr "nur ein Typ erlaubt" #, c-format msgid "wrong number of arguments, should be %d" @@ -5398,47 +5435,73 @@ msgstr "" "lesen Sie die Sektion \"CONFIGURATION FILE\" in \"git help worktree\" für " "Details" -msgid "--get-color and variable type are incoherent" -msgstr "Angabe von --get-color und Variablentyp sind ungültig." +msgid "Other" +msgstr "Sonstiges" -msgid "only one action at a time" -msgstr "Nur eine Aktion erlaubt." +msgid "respect include directives on lookup" +msgstr "beachtet \"include\"-Direktiven beim Nachschlagen" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only ist nur anwendbar auf --list oder --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "Konnte Konfigurationsdatei '%s' nicht lesen." -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"--show-origin ist nur anwendbar auf --get, --get-all, --get-regexp und --list" +msgid "error processing config file(s)" +msgstr "Fehler beim Verarbeiten der Konfigurationsdatei(en)." -msgid "--default is only applicable to --get" -msgstr "--default ist nur anwendbar auf --get" +msgid "Filter options" +msgstr "Filter-Optionen" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "" -"--comment darf nur für die Operationen add/set/replace verwendet werden" +msgid "return all values for multi-valued config options" +msgstr "alle Werte für mehrwertige Konfigurationsoptionen zurückgeben" + +msgid "interpret the name as a regular expression" +msgstr "den Namen als regulären Ausdruck interpretieren" + +msgid "show config with values matching the pattern" +msgstr "Anzeige von Konfiguration mit Werten, die dem Muster entsprechen" + +msgid "use string equality when comparing values to value pattern" +msgstr "String-Gleichheit beim Vergleich von Werten mit Wertmustern verwenden" + +msgid "URL" +msgstr "URL" + +msgid "show config matching the given URL" +msgstr "Konfiguration für die angegebene URL anzeigen" + +msgid "value" +msgstr "Wert" + +msgid "use default value when missing entry" +msgstr "Standardwert verwenden, wenn Eintrag fehlt" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value wird nur zusammen mit 'Wert-Muster' angewendet" -#, c-format -msgid "unable to read config file '%s'" -msgstr "Konnte Konfigurationsdatei '%s' nicht lesen." +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= kann nicht mit --all oder --url= verwendet werden" -msgid "error processing config file(s)" -msgstr "Fehler beim Verarbeiten der Konfigurationsdatei(en)." +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= kann nicht mit --all, --regexp oder --value verwendet werden" -msgid "editing stdin is not supported" -msgstr "Das Bearbeiten der Standard-Eingabe wird nicht unterstützt." +msgid "Filter" +msgstr "Filter" -msgid "editing blobs is not supported" -msgstr "Das Bearbeiten von Blobs wird nicht unterstützt." +msgid "replace multi-valued config option with new value" +msgstr "mehrwertige Konfigurationsoption durch einen neuen Wert ersetzen" -#, c-format -msgid "cannot create configuration file %s" -msgstr "Konnte Konfigurationsdatei '%s' nicht erstellen." +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"menschenlesbare Kommentarzeichenfolge (# wird bei Bedarf vorangestellt)" + +msgid "add a new line without altering any existing values" +msgstr "eine neue Zeile hinzufügen, ohne bestehende Werte zu ändern" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value gilt nur mit --value=<pattern>" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append kann nicht mit --value=<pattern> verwendet werden" #, c-format msgid "" @@ -5453,6 +5516,86 @@ msgstr "" msgid "no such section: %s" msgstr "Sektion nicht gefunden: %s" +msgid "editing stdin is not supported" +msgstr "Das Bearbeiten der Standard-Eingabe wird nicht unterstützt." + +msgid "editing blobs is not supported" +msgstr "Das Bearbeiten von Blobs wird nicht unterstützt." + +#, c-format +msgid "cannot create configuration file %s" +msgstr "Konnte Konfigurationsdatei '%s' nicht erstellen." + +msgid "Action" +msgstr "Aktion" + +msgid "get value: name [<value-pattern>]" +msgstr "Wert zurückgeben: Name [<Wert-Muster>]" + +msgid "get all values: key [<value-pattern>]" +msgstr "alle Werte zurückgeben: Schlüssel [<Wert-Muster>]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "Werte für den regulären Ausdruck zurückgeben: Name-Regex <Wert-Muster>" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "Wert spezifisch für eine URL zurückgeben: section[.var] URL" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "alle passenden Variablen ersetzen: Name Wert [<Wert-Muster>]" + +msgid "add a new variable: name value" +msgstr "neue Variable hinzufügen: Name Wert" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "eine Variable entfernen: Name [<Wert-Muster>]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "alle Treffer entfernen: Name [<Wert-Muster>]" + +msgid "rename section: old-name new-name" +msgstr "eine Sektion umbenennen: alter-Name neuer-Name" + +msgid "remove a section: name" +msgstr "eine Sektion entfernen: Name" + +msgid "list all" +msgstr "alles auflisten" + +msgid "open an editor" +msgstr "einen Editor öffnen" + +msgid "find the color configured: slot [<default>]" +msgstr "die konfigurierte Farbe finden: Slot [<Standard>]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "die Farbeinstellung finden: Slot [Standard-Ausgabe-ist-Terminal]" + +msgid "with --get, use default value when missing entry" +msgstr "mit --get, benutze den Standardwert, wenn der Eintrag fehlt" + +msgid "--get-color and variable type are incoherent" +msgstr "Angabe von --get-color und Variablentyp sind ungültig." + +msgid "no action specified" +msgstr "keine Aktion angegeben" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only ist nur anwendbar auf --list oder --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin ist nur anwendbar auf --get, --get-all, --get-regexp und --list" + +msgid "--default is only applicable to --get" +msgstr "--default ist nur anwendbar auf --get" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "" +"--comment darf nur für die Operationen add/set/replace verwendet werden" + msgid "print sizes in human readable format" msgstr "gibt Größenangaben in menschenlesbaren Format aus" @@ -5948,8 +6091,8 @@ msgstr "" "zu umgehen.\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n" +msgid "%s did not send all necessary objects" +msgstr "%s hat nicht alle erforderlichen Objekte gesendet" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -5988,8 +6131,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "Option \"%s\" wird ignoriert für %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "Option \"%s\" wird für %s ignoriert" #, c-format msgid "%s is not a valid object" @@ -6306,6 +6449,9 @@ msgstr "Konfiguration" msgid "config key storing a list of repository paths" msgstr "Konfigurationsschlüssel für eine Liste von Repository-Pfaden" +msgid "keep going even if command fails in a repository" +msgstr "weiterarbeiten, auch wenn der Befehl in einem Repository fehlschlägt" + msgid "missing --config=<config>" msgstr "Option --config=<Konfiguration> fehlt" @@ -6676,6 +6822,9 @@ msgstr "mehr Gründlichkeit (erhöht Laufzeit)" msgid "enable auto-gc mode" msgstr "\"auto-gc\" Modus aktivieren" +msgid "perform garbage collection in the background" +msgstr "Garbage Collection im Hintergrund ausführen" + msgid "force running gc even if there may be another gc running" msgstr "" "Ausführung von \"git gc\" erzwingen, selbst wenn ein anderes\n" @@ -6779,6 +6928,9 @@ msgstr "Aufgabe '%s' kann nicht mehrfach ausgewählt werden" msgid "run tasks based on the state of the repository" msgstr "Aufgaben abhängig vom Zustand des Repositories ausführen" +msgid "perform maintenance in the background" +msgstr "Wartung im Hintergrund ausführen" + msgid "frequency" msgstr "Häufigkeit" @@ -7655,9 +7807,6 @@ msgstr "-L<Bereich>:<Datei> kann nicht mit Pfadspezifikation verwendet werden" msgid "Final output: %d %s\n" msgstr "letzte Ausgabe: %d %s\n" -msgid "unable to create temporary object directory" -msgstr "konnte temporäres Objektverzeichnis nicht erstellen" - #, c-format msgid "git show %s: bad file" msgstr "git show %s: ungültige Datei" @@ -7781,8 +7930,11 @@ msgstr "die Serie als n-te Fassung kennzeichnen" msgid "max length of output filename" msgstr "maximale Länge des Dateinamens für die Ausgabe" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "[RFC PATCH] statt [PATCH] verwenden" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "<rfc> (standardmäßig 'RFC') vor 'PATCH' hinzufügen" msgid "cover-from-description-mode" msgstr "Modus für Erstellung des Deckblattes aus der Beschreibung" @@ -8058,11 +8210,11 @@ msgstr "" "verwendet werden" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<Programm>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<Programm>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<Schlüssel>]\n" " [--symref] [<Repository> [<Muster>...]]" @@ -8078,8 +8230,11 @@ msgstr "Pfad zu \"git-upload-pack\" auf der Gegenseite" msgid "limit to tags" msgstr "auf Tags einschränken" -msgid "limit to heads" -msgstr "auf Branches einschränken" +msgid "limit to branches" +msgstr "Beschränkung auf Branches" + +msgid "deprecated synonym for --branches" +msgstr "veraltetes Synonym für --branches" msgid "do not show peeled tags" msgstr "keine Tags anzeigen, die andere Tags enthalten" @@ -8231,15 +8386,6 @@ msgstr "einen diff3 basierten Merge verwenden" msgid "use a zealous diff3 based merge" msgstr "einen eifrigen diff3 basierten Merge verwenden" -msgid "for conflicts, use our version" -msgstr "bei Konflikten unsere Variante verwenden" - -msgid "for conflicts, use their version" -msgstr "bei Konflikten ihre Variante verwenden" - -msgid "for conflicts, use a union version" -msgstr "bei Konflikten eine gemeinsame Variante verwenden" - msgid "<algorithm>" msgstr "<Algorithmus>" @@ -8719,6 +8865,9 @@ msgstr "" msgid "write multi-pack bitmap" msgstr "schreibe Multi-Pack-Bitmap" +msgid "write a new incremental MIDX" +msgstr "ein neues inkrementelles MIDX schreiben" + msgid "write multi-pack index containing only given indexes" msgstr "Multi-Pack-Index schreiben, der nur die gegebenen Indexe enthält" @@ -10805,6 +10954,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +msgstr "das Referenzformat angeben, in das konvertiert werden soll" + +msgid "perform a non-destructive dry-run" +msgstr "einen zerstörungsfreien Trockenlauf durchführen" + +msgid "missing --ref-format=<format>" +msgstr "fehlendes --ref-format=<Format>" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "das Repository verwendet bereits das Format '%s'" + +msgid "enable strict checking" +msgstr "strenge Kontrolle aktivieren" + +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' nimmt keine Argumente an" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -11092,9 +11266,6 @@ msgstr "* Remote-Repository %s" msgid " Fetch URL: %s" msgstr " URL zum Abholen: %s" -msgid "(no URL)" -msgstr "(keine URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -11103,6 +11274,9 @@ msgstr "(keine URL)" msgid " Push URL: %s" msgstr " URL zum Versenden: %s" +msgid "(no URL)" +msgstr "(keine URL)" + #, c-format msgid " HEAD branch: %s" msgstr " Hauptbranch: %s" @@ -11212,10 +11386,6 @@ msgstr "nur URLs für Push ausgeben" msgid "return all URLs" msgstr "alle URLs ausgeben" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "Keine URLs für Remote-Repository '%s' konfiguriert." - msgid "manipulate push URLs" msgstr "URLs für \"push\" manipulieren" @@ -12235,12 +12405,12 @@ msgstr "Unbekannter Hash-Algorithmus" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<Muster>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<Muster>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -12263,11 +12433,11 @@ msgstr "Referenz nicht vorhanden" msgid "failed to look up reference" msgstr "Fehler beim Nachschlagen der Referenz" -msgid "only show tags (can be combined with heads)" -msgstr "nur Tags anzeigen (kann mit \"heads\" kombiniert werden)" +msgid "only show tags (can be combined with --branches)" +msgstr "nur Tags anzeigen (kann mit --branches kombiniert werden)" -msgid "only show heads (can be combined with tags)" -msgstr "nur Branches anzeigen (kann mit \"tags\" kombiniert werden)" +msgid "only show branches (can be combined with --tags)" +msgstr "nur Branches anzeigen (kann mit --tags kombiniert werden)" msgid "check for reference existence without resolving" msgstr "Prüfung auf Vorhandensein einer Referenz, ohne diese aufzulösen" @@ -12326,6 +12496,10 @@ msgstr "" "Fehler beim Erstellen eines Verzeichnisses für Datei eines partiellen " "Checkouts" +#, c-format +msgid "unable to fdopen %s" +msgstr "kann %s nicht öffnen" + msgid "failed to initialize worktree config" msgstr "Fehler beim Initialisieren der Arbeitsverzeichnis-Konfiguration" @@ -12793,8 +12967,8 @@ msgid "couldn't hash object from '%s'" msgstr "Hash eines Objektes von '%s' konnte nicht erzeugt werden" #, c-format -msgid "unexpected mode %o\n" -msgstr "unerwarteter Modus %o\n" +msgid "unexpected mode %o" +msgstr "unerwarteter Modus %o" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "" @@ -12919,14 +13093,14 @@ msgstr "" "verweigert." #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "Klonen von '%s' in Submodul-Pfad '%s' fehlgeschlagen." - -#, c-format msgid "directory not empty: '%s'" msgstr "Verzeichnis ist nicht leer: '%s'" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "Klonen von '%s' in Submodul-Pfad '%s' fehlgeschlagen." + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "Konnte Submodul-Verzeichnis '%s' nicht finden." @@ -13297,9 +13471,11 @@ msgstr "Grund für die Aktualisierung" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <Key-ID>] [-f] [-m <Beschreibung> | -F <Datei>] [-e]\n" +" [(--trailer <Token>[(=|:)<Wert>])...]\n" " <Tagname> [<Commit> | <Objekt>]" msgid "git tag -d <tagname>..." @@ -14189,9 +14365,6 @@ msgstr "nicht erkannter Kopfbereich: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Dem Repository fehlen folgende vorausgesetzte Commits:" -msgid "need a repository to verify a bundle" -msgstr "um ein Paket zu überprüfen wird ein Repository benötigt" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14615,6 +14788,9 @@ msgstr "Empfangen was in das Repository übertragen wurde" msgid "Manage reflog information" msgstr "Reflog Informationen verwalten" +msgid "Low-level access to refs" +msgstr "Low-Level Zugang zu Referenzen" + msgid "Manage set of tracked repositories" msgstr "Menge von hinterlegten Repositories verwalten" @@ -14925,6 +15101,14 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "" "Commit-Graph erforderlicher Commit-Daten Chunk fehlt oder ist beschädigt" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"deaktiviere Bloom-Filter für die Commit-Graph-Ebene '%s' aufgrund " +"inkompatibler Einstellungen" + msgid "commit-graph has no base graphs chunk" msgstr "Commit-Graph hat keinen Basis-Graph-Chunk" @@ -15052,6 +15236,14 @@ msgstr "" "versuche einen Commit-Graph zu schreiben, aber 'core.commitGraph' ist " "deaktiviert" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"versuche, einen Commit-Graphen zu schreiben, aber 'commitGraph." +"changedPathsVersion' (%d) wird nicht unterstützt" + msgid "too many commits to write graph" msgstr "zu viele Commits zum Schreiben des Graphen" @@ -16941,17 +17133,21 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <Pfad>] [-c <Name>=<Wert>]\n" " [--exec-path[=<Pfad>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<Pfad>] [--work-tree=<Pfad>] [--namespace=<Name>]\n" -" [--config-env=<Name>=<Umgebungsvariable>] <Befehl> [<Argumente>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<Pfad>]\n" +" [--work-tree=<Pfad>] [--namespace=<Name>] [--config-" +"env=<Name>=<Umgebungsvariable>]\n" +" <Befehl> [<Argumente>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -17293,13 +17489,13 @@ msgstr "" "Sie können diese Warnung mit `git config advice.ignoredHook false` " "deaktivieren." +msgid "not a git repository" +msgstr "kein Git-Repository" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "Argument für --packfile muss ein gültiger Hash sein ('%s' erhalten)" -msgid "not a git repository" -msgstr "kein Git-Repository" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "negativer Wert für http.postBuffer; benutze Standardwert %d" @@ -17312,6 +17508,9 @@ msgstr "" "Das Anheften des öffentlichen Schlüssels wird mit cURL < 7.39.0 nicht " "unterstützt" +msgid "Unknown value for http.proactiveauth" +msgstr "Unbekannter Wert für http.proactiveauth" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE wird mit cURL < 7.44.0 nicht unterstützt." @@ -17328,6 +17527,12 @@ msgstr "" msgid "Could not set SSL backend to '%s': already set" msgstr "Konnte SSL-Backend nicht zu '%s' setzen: bereits gesetzt" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "Lesen von Cookies von http.cookiefile '-' verweigert" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "http.savecookies wird bei leerem http.cookiefile ignoriert" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17470,13 +17675,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Konnte '%s.lock' nicht erstellen: %s" +msgid "unable to create temporary object directory" +msgstr "konnte temporäres Objektverzeichnis nicht erstellen" + #, c-format msgid "could not write loose object index %s" msgstr "konnte den losen Objektindex %s nicht schreiben" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "Fehler beim Schreiben des losen Objektindexes %s\n" +msgid "failed to write loose object index %s" +msgstr "Fehler beim Schreiben des losen Objektindex %s" #, c-format msgid "unexpected line: '%s'" @@ -17505,9 +17713,10 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Fehler beim Merge von Submodul %s (Commits nicht vorhanden)." #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" +msgid "error: failed to merge submodule %s (repository corrupt)" msgstr "" -"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)" +"Fehler: Submodul %s konnte nicht zusammengeführt werden (Repository " +"beschädigt)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17537,12 +17746,13 @@ msgstr "" "sind vorhanden:\n" "%s" -msgid "failed to execute internal merge" -msgstr "Fehler bei Ausführung des internen Merges" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "Fehler: Der interne Merge für %s konnte nicht ausgeführt werden" #, c-format -msgid "unable to add %s to database" -msgstr "konnte %s nicht zur Datenbank hinzufügen" +msgid "error: unable to add %s to database" +msgstr "Fehler: kann %s nicht zur Datenbank hinzufügen" #, c-format msgid "Auto-merging %s" @@ -17640,12 +17850,12 @@ msgstr "" "KONFLIKT (umbenennen/löschen): %s zu %s in %s umbenannt, aber in %s gelöscht." #, c-format -msgid "cannot read object %s" -msgstr "kann Objekt %s nicht lesen" +msgid "error: cannot read object %s" +msgstr "Fehler: kann Objekt %s nicht lesen" #, c-format -msgid "object %s is not a blob" -msgstr "Objekt %s ist kein Blob" +msgid "error: object %s is not a blob" +msgstr "Fehler: Objekt %s ist kein Blob" #, c-format msgid "" @@ -17698,7 +17908,7 @@ msgstr "" #. conflict in a submodule. The first argument is the submodule #. name, and the second argument is the abbreviated id of the #. commit that needs to be merged. For example: -#. - go to submodule (mysubmodule), and either merge commit abc1234" +#. - go to submodule (mysubmodule), and either merge commit abc1234" #. #, c-format msgid "" @@ -17788,6 +17998,11 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "weiß nicht was mit %06o %s '%s' zu machen ist" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "" +"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Spule Submodul %s zu dem folgenden Commit vor:" @@ -17828,6 +18043,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "Fehler beim Merge von Submodul %s (mehrere Merges gefunden)" +msgid "failed to execute internal merge" +msgstr "Fehler bei Ausführung des internen Merges" + +#, c-format +msgid "unable to add %s to database" +msgstr "konnte %s nicht zur Datenbank hinzufügen" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -17935,6 +18157,14 @@ msgstr "" "KONFLIKT (umbenennen/umbenennen): Benenne Verzeichnis um %s->%s in %s.\n" "Benenne Verzeichnis um %s->%s in %s" +#, c-format +msgid "cannot read object %s" +msgstr "kann Objekt %s nicht lesen" + +#, c-format +msgid "object %s is not a blob" +msgstr "Objekt %s ist kein Blob" + msgid "modify" msgstr "ändern" @@ -18019,10 +18249,6 @@ msgstr "Zeile konnte nicht geparst werden: %s" msgid "malformed line: %s" msgstr "fehlerhafte Zeile: %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein" - msgid "could not load pack" msgstr "Paket konnte nicht geladen werden" @@ -18030,6 +18256,21 @@ msgstr "Paket konnte nicht geladen werden" msgid "could not open index for %s" msgstr "konnte Index für %s nicht öffnen" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "kann '%s' nicht mit '%s' verknüpfen" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "kann kein inkrementelles MIDX mit Bitmap schreiben" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein" + msgid "Adding packfiles to multi-pack-index" msgstr "Packdateien zum Multi-Pack-Index hinzufügen" @@ -18055,18 +18296,34 @@ msgstr "keine Packdateien zum Indizieren." msgid "refusing to write multi-pack .bitmap without any objects" msgstr "Schreiben der Multi-Pack-Bitmap ohne Objekte abgelehnt" +msgid "unable to create temporary MIDX layer" +msgstr "konnte keine temporäre MIDX-Ebene erstellen" + msgid "could not write multi-pack bitmap" msgstr "Multi-Pack-Bitmap konnte nicht geschrieben werden" +msgid "unable to open multi-pack-index chain file" +msgstr "Multi-Pack-Indexketten-Datei kann nicht geöffnet werden" + +msgid "unable to rename new multi-pack-index layer" +msgstr "neue Multi-Pack-Index-Ebene konnte nicht umbenannt werden" + msgid "could not write multi-pack-index" msgstr "Multi-Pack-Index konnte nicht geschrieben werden" +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "" +"kann Pakete aus einem inkrementellen Multi-Pack-Index nicht ablaufen lassen" + msgid "Counting referenced objects" msgstr "Referenzierte Objekte zählen" msgid "Finding and deleting unreferenced packfiles" msgstr "Suchen und Löschen von unreferenzierten Pack-Dateien" +msgid "cannot repack an incremental multi-pack-index" +msgstr "kann einen inkrementellen Multi-Pack-Index nicht neu packen" + msgid "could not start pack-objects" msgstr "Konnte 'pack-objects' nicht ausführen" @@ -18129,6 +18386,27 @@ msgstr "multi-pack-index Pack-Name Chunk ist zu klein" msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "Falsche Reihenfolge bei Multi-Pack-Index Pack-Namen: '%s' vor '%s'" +msgid "multi-pack-index chain file too small" +msgstr "Multi-Pack-Index-Kettendatei zu klein" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "Paketanzahl im Basis-MIDX zu hoch: %<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "Objektanzahl in Basis-MIDX zu hoch: %<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "ungültige Multi-Pack-Index-Kette: Zeile '%s' ist kein Hash" + +msgid "unable to find all multi-pack index files" +msgstr "konnte nicht alle Multi-Pack-Indexdateien finden" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "ungültige MIDX-Objektposition, MIDX ist wahrscheinlich beschädigt" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "Ungültige pack-int-id: %u (%u Pakete insgesamt)" @@ -18147,10 +18425,6 @@ msgstr "" msgid "multi-pack-index large offset out of bounds" msgstr "multi-pack-index großer Offset außerhalb der Grenzen" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s" - msgid "multi-pack-index file exists, but failed to parse" msgstr "Multi-Pack-Index-Datei existiert, aber das Parsen schlug fehl" @@ -18369,6 +18643,14 @@ msgid "missing mapping of %s to %s" msgstr "fehlende Abbildung von %s auf %s" #, c-format +msgid "unable to open %s" +msgstr "kann %s nicht öffnen" + +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "die Dateien '%s' und '%s' unterscheiden sich im Inhalt" + +#, c-format msgid "unable to write file %s" msgstr "Konnte Datei %s nicht schreiben." @@ -18455,10 +18737,6 @@ msgid "%s is not a valid '%s' object" msgstr "%s ist kein gültiges '%s' Objekt" #, c-format -msgid "unable to open %s" -msgstr "kann %s nicht öffnen" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "Hash für %s stimmt nicht überein (%s erwartet)." @@ -18489,7 +18767,7 @@ msgstr "%s [ungültiges Objekt]" #. TRANSLATORS: This is a line of ambiguous commit #. object output. E.g.: #. * -#. "deadbeef commit 2021-01-01 - Some Commit Message" +#. "deadbeef commit 2021-01-01 - Some Commit Message" #. #, c-format msgid "%s commit %s - %s" @@ -18498,7 +18776,7 @@ msgstr "%s Commit %s - %s" #. TRANSLATORS: This is a line of ambiguous #. tag object output. E.g.: #. * -#. "deadbeef tag 2022-01-01 - Some Tag Message" +#. "deadbeef tag 2022-01-01 - Some Tag Message" #. * #. The second argument is the YYYY-MM-DD found #. in the tag. @@ -18514,7 +18792,7 @@ msgstr "%s Tag %s - %s" #. tag object output where we couldn't parse #. the tag itself. E.g.: #. * -#. "deadbeef [bad tag, could not parse it]" +#. "deadbeef [bad tag, could not parse it]" #. #, c-format msgid "%s [bad tag, could not parse it]" @@ -18655,6 +18933,17 @@ msgstr "Konnte Objekt '%s' nicht parsen." msgid "hash mismatch %s" msgstr "Hash stimmt nicht mit %s überein." +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "doppelter Eintrag beim Schreiben des Bitmap-Index: %s" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "versuchte, nicht gewählten Commit '%s' zu speichern" + +msgid "too many pseudo-merges" +msgstr "zu viele Pseudo-Merges" + msgid "trying to write commit not in index" msgstr "Versuch, einen Commit zu schreiben, der nicht im Index steht" @@ -18679,6 +18968,17 @@ msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "" "beschädigte Bitmap-Indexdatei (zu kurz, um in die Lookup-Tabelle zu passen)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"beschädigte Bitmap-Indexdatei (zu kurz für den Pseudo-Merge-Tabellenkopf)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "beschädigte Bitmap-Indexdatei (zu kurz für die Pseudo-Merge-Tabelle)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "beschädigte Bitmap-Indexdatei, Pseudo-Merge-Tabelle zu kurz" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "duplizierter Eintrag im Bitmap-Index: '%s'" @@ -18776,6 +19076,10 @@ msgid "mismatch in bitmap results" msgstr "Unstimmigkeiten bei Bitmap-Ergebnissen" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "Pseudo-Merge-Index außerhalb des Bereichs (%<PRIu32> >= %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "konnte '%s' in Paket '%s' bei Offset %<PRIuMAX> nicht finden" @@ -19145,6 +19449,10 @@ msgstr "Kann Thread für lstat nicht erzeugen: %s" msgid "unable to parse --pretty format" msgstr "Konnte --pretty Format nicht parsen." +msgid "lazy fetching disabled; some objects may not be available" +msgstr "" +"lazy fetching deaktiviert; einige Objekte sind möglicherweise nicht verfügbar" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "Promisor-Remote: konnte Fetch-Subprozess nicht abspalten" @@ -19170,6 +19478,67 @@ msgstr "object-info: erwartete Flush nach Argumenten" msgid "Removing duplicate objects" msgstr "Lösche doppelte Objekte" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "Pseudo-Merge-Regex konnte nicht geladen werden für %s: '%s'" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s muss nicht-negativ sein, Standardwert wird verwendet" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s muss zwischen 0 und 1 liegen, Standardwert wird verwendet" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s muss positiv sein, verwende Standardwert" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "Pseudo-Merge-Gruppe '%s' fehlt erforderliches Muster" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"Pseudo-Merge-Gruppe '%s' hat einen instabilen vor einem stabilen " +"Schwellenwert" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"Pseudo-Merge-Regex aus der Konfiguration hat zu viele Capture-Gruppen " +"(maximum=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"erweiterter Pseudo-Merge liest außerhalb des Bereichs (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"erweiterter Pseudo-Merge-Eintrag ist zu kurz (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "konnte keinen Pseudo-Merge für Commit %s bei Offset %<PRIuMAX> finden" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"erweiterte Pseudo-Merge-Suche außerhalb des Bereichs (%<PRIu32> >= %<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "Lesen außerhalb des zulässigen Bereichs: (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "konnte erweiterte Pseudo-Merge-Tabelle für Commit %s nicht lesen" + msgid "could not start `log`" msgstr "Konnte `log` nicht starten." @@ -19604,6 +19973,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "erwartetes Format: %%(ahead-behind:<Commit>)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "erwartetes Format: %%(is-base:<committish>)" + +#, c-format msgid "malformed field name: %.*s" msgstr "Fehlerhafter Feldname: %.*s" @@ -19778,11 +20151,18 @@ msgstr "Log für Referenz %s unerwartet bei %s beendet." msgid "log for %s is empty" msgstr "Log für %s ist leer." +msgid "refusing to force and skip creation of reflog" +msgstr "Erzwingen der Aktion verweigert; überspringe Erstellung des Reflogs" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "verweigere Aktualisierung einer Referenz mit fehlerhaftem Namen '%s'" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "Aktualisierung von Pseudoreferenz '%s' verweigert" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "update_ref für Referenz '%s' fehlgeschlagen: %s" @@ -19815,6 +20195,34 @@ msgid "could not delete references: %s" msgstr "konnte Referenzen nicht entfernen: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "" +"Trockenlauf der Migration von Referenzen abgeschlossen. Das Ergebnis kann " +"unter '%s' gefunden werden.\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "konnte das temporäre Migrationsverzeichnis '%s' nicht entfernen" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "migrierte Referenzen befinden sich unter '%s'" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"kann Referenz '%s' nicht sperren: erwartete symbolische Referenz mit Ziel " +"'%s': ist aber eine reguläre Referenz" + +#, c-format +msgid "cannot open directory %s" +msgstr "Verzeichnis %s kann nicht geöffnet werden" + +msgid "Checking references consistency" +msgstr "Überprüfung der Konsistenz der Referenzen" + +#, c-format msgid "refname is dangerous: %s" msgstr "Referenzname ist gefährlich: %s" @@ -20460,12 +20868,15 @@ msgstr "lade nur Metadaten des Branches herunter, der ausgecheckt wird" msgid "create repository within 'src' directory" msgstr "Repository im Verzeichnis 'src' erstellen" +msgid "specify if tags should be fetched during clone" +msgstr "Angabe, ob Tags während des Klonens abgerufen werden sollen" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <Haupt-Branch>] [--full-clone]\n" -"\t[--[no-]src] <URL> [<Eintragung>]" +"\t[--[no-]src] [--[no-]tags] <URL> [<Eintragung>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -20484,6 +20895,10 @@ msgid "could not configure remote in '%s'" msgstr "konnte Remote-Repository in '%s' nicht konfigurieren" #, c-format +msgid "could not disable tags in '%s'" +msgstr "konnte die Tags in '%s' nicht deaktivieren" + +#, c-format msgid "could not configure '%s'" msgstr "konnte '%s' nicht konfigurieren" @@ -20993,6 +21408,50 @@ msgstr "" "refs/heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' akzeptiert keine Merge-Commits" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick' nimmt keinen Merge-Commit an. Wenn Sie den Merge wiederholen\n" +"wollen, verwenden Sie 'merge -C' auf den Commit." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword' erfordert keinen Merge-Commit. Wenn Sie\n" +"den Merge wiederholen und die Commit-Nachricht\n" +"neu formulieren wollen, verwenden Sie\n" +"'merge -c' auf den Commit" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'edit' nimmt keinen Merge-Commit an. Wenn Sie den Merge wiederholen\n" +"wollen, verwenden Sie 'merge -C' auf den Commit und dann\n" +"break', um die Kontrolle zurückzugewinnen, sodass Sie\n" +"'git commit --amend && git rebase --continue' ausführen können." + +msgid "cannot squash merge commit into another commit" +msgstr "kann einen Merge-Commit nicht mit einem anderen Commit zusammenfassen" + +#, c-format msgid "invalid command '%.*s'" msgstr "ungültiger Befehl '%.*s'" @@ -21110,9 +21569,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "kann HEAD nicht lesen" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "konnte '%s' nicht nach '%s' kopieren" +msgid "could not write commit message file" +msgstr "konnte keine Commit-Beschreibungsdatei schreiben" #, c-format msgid "" @@ -21522,6 +21980,22 @@ msgstr "Kann nicht zum aktuellen Arbeitsverzeichnis zurückwechseln." msgid "failed to stat '%*s%s%s'" msgstr "Konnte '%*s%s%s' nicht lesen." +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' nicht absolut" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"dubiose Besitzverhältnisse im Repository bei '%s' entdeckt\n" +"%sUm eine Ausnahme für dieses Verzeichnis hinzuzufügen, rufen Sie auf:\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Konnte aktuelles Arbeitsverzeichnis nicht lesen." @@ -21543,18 +22017,6 @@ msgstr "" "Stoppe bei Dateisystemgrenze (GIT_DISCOVERY_ACROSS_FILESYSTEM nicht gesetzt)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"dubiose Besitzverhältnisse im Repository bei '%s' entdeckt\n" -"%sUm eine Ausnahme für dieses Verzeichnis hinzuzufügen, rufen Sie auf:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "" "kann Bare-Repository '%s' nicht verwenden (safe.bareRepository ist '%s')" @@ -21862,6 +22324,14 @@ msgstr "" "Git-Verzeichnis des Submoduls '%s' ist im Git-Verzeichnis '%.*s' enthalten." #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "erwartete, dass '%.*s' im Submodulpfad '%s' kein symbolischer Link ist" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "erwartete, dass der Submodulpfad '%s' kein symbolischer Link ist" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -21900,10 +22370,6 @@ msgstr "'lstat' für '%s' fehlgeschlagen" msgid "no remote configured to get bundle URIs from" msgstr "kein Remote-Repository zum Erhalten von Bundle-URIs konfiguriert" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "Remote-Repository '%s' hat keine konfigurierte URL" - msgid "could not get the bundle-uri list" msgstr "konnte die Bundle-uri-Liste nicht erhalten" @@ -21986,6 +22452,24 @@ msgstr "Token" msgid "command token to send to the server" msgstr "Befehlstoken, der an den Server gesendet werden soll" +msgid "unit-test [<options>]" +msgstr "unit-test [<Optionen>]" + +msgid "immediately exit upon the first failed test" +msgstr "beim ersten fehlgeschlagenen Test sofort abbrechen" + +msgid "suite[::test]" +msgstr "suite[::test]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "nur Testsuite oder einzelnen Test ausführen <suite[::test]>" + +msgid "suite" +msgstr "Suite" + +msgid "exclude test suite <suite>" +msgstr "Testsuite <Suite> ausschließen" + #, c-format msgid "running trailer command '%s' failed" msgstr "Ausführen des Anhang-Befehls '%s' fehlgeschlagen" @@ -23235,6 +23719,10 @@ msgstr "'%s.final' enthält die verfasste E-Mail.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases ist mit anderen Optionen inkompatibel\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "" +"--dump-aliases und --translate-aliases schließen sich gegenseitig aus\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -23459,24 +23947,24 @@ msgid "Failed to send %s\n" msgstr "Fehler beim Senden %s\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Probeversand %s\n" +msgid "Dry-Sent %s" +msgstr "Probeversand %s" #, perl-format -msgid "Sent %s\n" -msgstr "%s gesendet\n" +msgid "Sent %s" +msgstr "%s gesendet" -msgid "Dry-OK. Log says:\n" -msgstr "Probeversand OK. Log enthält:\n" +msgid "Dry-OK. Log says:" +msgstr "Probelauf OK. Das Protokoll enthält:" -msgid "OK. Log says:\n" -msgstr "OK. Log enthält:\n" +msgid "OK. Log says:" +msgstr "OK. Das Protokoll enthält:" msgid "Result: " msgstr "Ergebnis: " -msgid "Result: OK\n" -msgstr "Ergebnis: OK\n" +msgid "Result: OK" +msgstr "Ergebnis: OK" #, perl-format msgid "can't open file %s" @@ -80,8 +80,8 @@ msgid "" msgstr "" "Project-Id-Version: git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-16 22:57+0000\n" -"PO-Revision-Date: 2024-04-20 17:11+0800\n" +"POT-Creation-Date: 2024-10-02 16:57+0000\n" +"PO-Revision-Date: 2024-10-04 23:03+0200\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" @@ -628,7 +628,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - laisser cette section non décidée et aller à la suivante non-décidée\n" @@ -639,9 +639,13 @@ msgstr "" "/ - rechercher une section correspondant à une regex donnée\n" "s - découper la section en sections plus petites\n" "e - éditer manuellement la section actuelle\n" -"p - afficher la section actuelle\n" +"p - afficher la section actuelle, 'P' pour utiliser un paginateur\n" "? - afficher l'aide\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "une seule lettre est attendue, mais '%s' a été reçu" + msgid "No previous hunk" msgstr "Pas de section précédente" @@ -690,9 +694,19 @@ msgstr "Découpée en %d sections." msgid "Sorry, cannot edit this hunk" msgstr "Désolé, impossible d'éditer cette section" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "commande inconnue : '%s' (utilisez '?' pour de l'aide)" + msgid "'git apply' failed" msgstr "'git apply' a échoué" +msgid "No changes." +msgstr "Aucune modification." + +msgid "Only binary files changed." +msgstr "Seuls des fichiers binaires ont changé." + #, c-format msgid "" "\n" @@ -1219,10 +1233,6 @@ msgstr[0] "Application du patch %%s avec %d rejet..." msgstr[1] "Application du patch %%s avec %d rejets..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "troncature du nom de fichier .rej en %.*s.rej" - -#, c-format msgid "cannot open %s" msgstr "impossible d'ouvrir %s" @@ -1320,6 +1330,15 @@ msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "" "tenter une fusion à 3 points, revenir à un rustinage normal en cas d'échec" +msgid "for conflicts, use our version" +msgstr "pour les conflits, utiliser notre version (our)" + +msgid "for conflicts, use their version" +msgstr "pour les conflits, utiliser leur version (their)" + +msgid "for conflicts, use a union version" +msgstr "pour les conflits, utiliser l'union des versions" + msgid "build a temporary index based on embedded index information" msgstr "" "construire un index temporaire fondé sur l'information de l'index embarqué" @@ -1370,6 +1389,9 @@ msgstr "préfixer tous les noms de fichier avec <root>" msgid "don't return error for empty patches" msgstr "ne pas renvoyer d'erreur pour les rustines vides" +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs et --union requièrent --3way" + #, c-format msgid "cannot stream blob %s" msgstr "impossible de transmettre le blob %s en flux" @@ -1443,6 +1465,9 @@ msgstr "nom d'objet invalide : %s" msgid "not a tree object: %s" msgstr "objet arbre invalide : %s" +msgid "unable to checkout working tree" +msgstr "impossible d'extraire la copie de travail" + #, c-format msgid "File not found: %s" msgstr "Fichier non trouvé : %s" @@ -1573,6 +1598,9 @@ msgstr "fichier gitattributes trop gros ignoré '%s'" msgid "ignoring overly large gitattributes blob '%s'" msgstr "blob gitattributes trop gros ignoré '%s'" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "impossible d'utiliser --attr-source ou GIT_ATTR_SOURCE sans dépôt" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "mauvais --attr-source ou GIT_ATTR_SOURCE" @@ -1654,6 +1682,10 @@ msgid "could not create file '%s'" msgstr "impossible de créer le fichier '%s'" #, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "impossible de démarrer 'show' pour l'objet '%s'" + +#, c-format msgid "could not read file '%s'" msgstr "impossible de lire le fichier '%s'" @@ -1887,13 +1919,6 @@ msgstr "impossible de chmod %cx '%s'" msgid "Unstaged changes after refreshing the index:" msgstr "Modifications non indexées après rafraîchissement de l'index :" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"le réglage add.interactive.useBuiltin a été supprimé !\n" -"Référez-vous à cette entrée dans 'git help config' pour plus de détails." - msgid "could not read the index" msgstr "impossible de lire l'index" @@ -2006,7 +2031,7 @@ msgid "adding embedded git repository: %s" msgstr "dépôt git embarqué ajouté : %s" msgid "Use -f if you really want to add them." -msgstr "Utilisez -f si vous voulez vraiment les ajouter" +msgstr "Utilisez -f si vous voulez vraiment les ajouter<." msgid "adding files failed" msgstr "échec de l'ajout de fichiers" @@ -2340,6 +2365,9 @@ msgstr "abandonne l'opération de patch mais garde HEAD où il est" msgid "show the patch being applied" msgstr "afficher le patch en cours d'application" +msgid "try to apply current patch again" +msgstr "essayer d'appliquer de nouveau la rustine" + msgid "record the empty patch as an empty commit" msgstr "enregistrer la rustine vide comme un commit vide" @@ -2398,9 +2426,6 @@ msgstr "git apply [<options>] [<patch>...]" msgid "could not redirect output" msgstr "impossible de rediriger la sortie" -msgid "git archive: Remote with no URL" -msgstr "git archive : Dépôt distant sans URL" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive : ACK/NACK attendu, paquet de nettoyage reçu" @@ -2556,9 +2581,6 @@ msgstr "" "Les options supportées sont : --term-good|--term-old et --term-bad|--term-" "new." -msgid "revision walk setup failed\n" -msgstr "échec de la préparation du parcours des révisions\n" - #, c-format msgid "could not open '%s' for appending" msgstr "impossible d'ouvrir '%s' en ajout" @@ -3321,6 +3343,9 @@ msgstr "La création d'un colis requiert un dépôt." msgid "do not show bundle details" msgstr "ne pas afficher les détails du colis" +msgid "need a repository to verify a bundle" +msgstr "la vérification d'un colis requiert un dépôt" + #, c-format msgid "%s is okay\n" msgstr "%s est correct\n" @@ -3351,7 +3376,7 @@ msgstr "%s nécessite des arguments" #, c-format msgid "%s takes no arguments" -msgstr "%s n'accepte aucune argument" +msgstr "%s n'accepte aucun argument" msgid "only one batch option may be specified" msgstr "une seule option de traitement ne peut être spécifiée à la fois" @@ -3556,9 +3581,14 @@ msgstr "git check-mailmap [<options>] <contact>..." msgid "also read contacts from stdin" msgstr "lire aussi les contacts depuis l'entrée standard" -#, c-format -msgid "unable to parse contact: %s" -msgstr "impossible d'analyser le contact : %s" +msgid "read additional mailmap entries from file" +msgstr "lire des entrées supplémentaires de mailmap depuis un fichier" + +msgid "blob" +msgstr "blob" + +msgid "read additional mailmap entries from blob" +msgstr "lire des entrées supplémentaires depuis un blob" msgid "no contacts specified" msgstr "aucun contact spécifié" @@ -3916,6 +3946,10 @@ msgid "'%s' cannot be used with switching branches" msgstr "'%s' ne peut pas être utilisé avec un basculement de branches" #, c-format +msgid "'%s' needs the paths to check out" +msgstr "'%s' requiert les chemins à extraire" + +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s' ne peut pas être utilisé avec '%s'" @@ -4351,6 +4385,14 @@ 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érifier à '%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'" @@ -4394,9 +4436,6 @@ 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" @@ -4686,7 +4725,7 @@ msgstr "git commit-tree : échec de la lecture" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4697,7 +4736,7 @@ msgstr "" "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" +" [-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" @@ -5195,15 +5234,61 @@ msgstr "" "d'index. Vérifiez que le disque n'est pas plein ou que le quota\n" "n'a pas été dépassé, puis lancez \"git restore --staged :/\" pour réparer." -msgid "git config [<options>]" -msgstr "git config [<options>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "" +"git config list [<option-de-fichier>] [<option-d-affichage>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "argument --type non reconnu, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<option-de-fichier>] [<option-d-affichage>] [--includes] [--" +"all] [--regexp] [--value=<valeur>] [--fixed-value] [--default=<défaut>] " +"<name>" -msgid "only one type at a time" -msgstr "qu'un seul type à la fois" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<option-de-fichier>] [--type=<type>] [--all] [--" +"value=<valeur>] [--fixed-value] <nom> <valeur>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<option-de-fichier>] [--all] [--value=<valeur>] [--fixed-" +"value] <nom> <valeur>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "" +"git config rename-section [<option-de-fichier>] <ancien-nom> <nouveau-nom>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<option-de-fichier>] <nom>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<option-de-fichier>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "" +"git config [<option-de-fichier>] --get-colorbool <nom> [<stdout-est-tty>]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<option-de-fichier>] [<option-d-affichage>] [--includes] [--" +"all] [--regexp=<regexp>] [--value=<valeur>] [--fixed-value] [--" +"default=<défaut>] <name>" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<option-de-fichier>] [--type=<type>] [--comment=<message>] " +"[--all] [--value=<valeur>] [--fixed-value] <nom> <valeur>" msgid "Config file location" msgstr "Emplacement du fichier de configuration" @@ -5229,56 +5314,6 @@ msgstr "blob-id" msgid "read config from given blob object" msgstr "lire la configuration depuis l'objet blob fourni" -msgid "Action" -msgstr "Action" - -msgid "get value: name [value-pattern]" -msgstr "obtenir la valeur : nom [motif-de-valeur]" - -msgid "get all values: key [value-pattern]" -msgstr "obtenir toutes les valeurs : clé [motif-de-valeur]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "obtenir les valeur pour la regexp : regex-de-nom [motif-de-valeur]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "obtenir la valeur spécifique pour l'URL : section[.var] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "" -"remplacer toutes les variables correspondant : nom valeur [motif-de-valeur]" - -msgid "add a new variable: name value" -msgstr "ajouter une nouvelle variable : nom valeur" - -msgid "remove a variable: name [value-pattern]" -msgstr "supprimer une variable : nom [motif-de-valeur]" - -msgid "remove all matches: name [value-pattern]" -msgstr "supprimer toutes les correspondances nom [motif-de-valeur]" - -msgid "rename section: old-name new-name" -msgstr "renommer une section : ancien-nom nouveau-nom" - -msgid "remove a section: name" -msgstr "supprimer une section : nom" - -msgid "list all" -msgstr "afficher tout" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "" -"utiliser l'égalité de chaînes lors de la comparaison de 'motif-de-valeur'" - -msgid "open an editor" -msgstr "ouvrir un éditeur" - -msgid "find the color configured: slot [default]" -msgstr "trouver la couleur configurée : slot [par défaut]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "trouver le réglage de la couleur : slot [stdout-est-tty]" - msgid "Type" msgstr "Type" @@ -5306,8 +5341,8 @@ msgstr "la valeur est un chemin (vers un fichier ou un répertoire)" msgid "value is an expiry date" msgstr "la valeur est une date d'expiration" -msgid "Other" -msgstr "Autre" +msgid "Display options" +msgstr "Options d'affichage" msgid "terminate values with NUL byte" msgstr "terminer les valeurs avec un caractère NUL" @@ -5315,9 +5350,6 @@ msgstr "terminer les valeurs avec un caractère NUL" msgid "show variable names only" msgstr "n'afficher que les noms de variable" -msgid "respect include directives on lookup" -msgstr "respecter les directives d'inclusion lors de la recherche" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "afficher l'origine de la configuration (fichier, entrée standard, blob, " @@ -5328,16 +5360,15 @@ msgstr "" "afficher la portée de configuration (arbre de travail, local, global, " "système, commande)" -msgid "value" -msgstr "valeur" +msgid "show config keys in addition to their values" +msgstr "afficher les clés de configuration en plus des valeurs" -msgid "with --get, use default value when missing entry" -msgstr "avec --get, utiliser le valeur par défaut quand l'entrée n'existe pas" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "argument --type non reconnu, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "" -"chaîne des commentaires lisibles par l'utilisateur (# sera ajouté en préfixe " -"selon les besoins)" +msgid "only one type at a time" +msgstr "qu'un seul type à la fois" #, c-format msgid "wrong number of arguments, should be %d" @@ -5414,47 +5445,77 @@ msgstr "" "la section \"CONFIGURATION FILE\" de \"git help worktree\" pour plus de " "détails" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color et le type de la variable sont incohérents" +msgid "Other" +msgstr "Autre" -msgid "only one action at a time" -msgstr "une seule action à la fois" +msgid "respect include directives on lookup" +msgstr "respecter les directives d'inclusion lors de la recherche" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only n'est applicable qu'avec --list ou --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "lecture du fichier de configuration '%s' impossible" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" +msgid "error processing config file(s)" +msgstr "erreur lors du traitement de fichier(s) de configuration" + +msgid "Filter options" +msgstr "Options de filtre" + +msgid "return all values for multi-valued config options" msgstr "" -"--show-origin n'est applicable qu'avec --get, --get-all, --get-regexp ou --" -"list" +"renvoyer toutes les valeurs pour les options de configuration multi-valeurs" -msgid "--default is only applicable to --get" -msgstr "--default n'est applicable qu'avec --get" +msgid "interpret the name as a regular expression" +msgstr "interpréter le nom comme une expression régulière" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment n'est applicable qu'avec les opérations add/set/replace" +msgid "show config with values matching the pattern" +msgstr "afficher les configurations dont le nom correspond au motif" + +msgid "use string equality when comparing values to value pattern" +msgstr "" +"utiliser l'égalité de chaînes lors de la comparaison des valeurs au motif de " +"valeur" + +msgid "URL" +msgstr "URL" + +msgid "show config matching the given URL" +msgstr "afficher les configs qui correspondent à l'URL donné" + +msgid "value" +msgstr "valeur" + +msgid "use default value when missing entry" +msgstr "utiliser le valeur par défaut quand l'entrée n'existe pas" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value ne s'applique qu'à 'motif-de-valeur'" -#, c-format -msgid "unable to read config file '%s'" -msgstr "lecture du fichier de configuration '%s' impossible" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= ne peut pas être utilisé avec --all ou --url=" -msgid "error processing config file(s)" -msgstr "erreur lors du traitement de fichier(s) de configuration" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= ne peut pas être utilisé avec --all, --regexp ou --value" -msgid "editing stdin is not supported" -msgstr "l'édition de stdin n'est pas supportée" +msgid "Filter" +msgstr "Filtre" -msgid "editing blobs is not supported" -msgstr "l'édition de blobs n'est pas supportée" +msgid "replace multi-valued config option with new value" +msgstr "remplacer l'option de config multi-valeur par la nouvelle valeur" -#, c-format -msgid "cannot create configuration file %s" -msgstr "création impossible du fichier de configuration '%s'" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"chaîne des commentaires lisibles par l'utilisateur (# sera ajouté en préfixe " +"selon les besoins)" + +msgid "add a new line without altering any existing values" +msgstr "ajouter une nouvelle ligne sans modifier les valeurs existantes" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value ne s'applique qu'avec --value=<motif>" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append ne s'applique pas avec --value=<motif>" #, c-format msgid "" @@ -5468,6 +5529,87 @@ msgstr "" msgid "no such section: %s" msgstr "section inexistante : %s" +msgid "editing stdin is not supported" +msgstr "l'édition de stdin n'est pas supportée" + +msgid "editing blobs is not supported" +msgstr "l'édition de blobs n'est pas supportée" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "création impossible du fichier de configuration '%s'" + +msgid "Action" +msgstr "Action" + +msgid "get value: name [<value-pattern>]" +msgstr "obtenir la valeur : nom [<motif-de-valeur>]" + +msgid "get all values: key [<value-pattern>]" +msgstr "obtenir toutes les valeurs : clé [<motif-de-valeur>]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "obtenir les valeur pour la regexp : name-regex [<motif-de-valeur>]" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "obtenir la valeur spécifique pour l'URL : section[.var] URL" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "" +"remplacer toutes les variables correspondant : nom valeur [<motif-de-valeur>]" + +msgid "add a new variable: name value" +msgstr "ajouter une nouvelle variable : nom valeur" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "supprimer une variable : nom [<motif-de-valeur>]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "supprimer toutes les correspondances nom [<motif-de-valeur>]" + +msgid "rename section: old-name new-name" +msgstr "renommer une section : ancien-nom nouveau-nom" + +msgid "remove a section: name" +msgstr "supprimer une section : nom" + +msgid "list all" +msgstr "afficher tout" + +msgid "open an editor" +msgstr "ouvrir un éditeur" + +msgid "find the color configured: slot [<default>]" +msgstr "trouver la couleur configurée : slot [<valeur-par-défaut>]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "trouver le réglage de la couleur : slot [<stdout-est-tty>]" + +msgid "with --get, use default value when missing entry" +msgstr "avec --get, utiliser le valeur par défaut quand l'entrée n'existe pas" + +msgid "--get-color and variable type are incoherent" +msgstr "--get-color et le type de la variable sont incohérents" + +msgid "no action specified" +msgstr "aucune action spécifiée" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only n'est applicable qu'avec --list ou --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin n'est applicable qu'avec --get, --get-all, --get-regexp ou --" +"list" + +msgid "--default is only applicable to --get" +msgstr "--default n'est applicable qu'avec --get" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment n'est applicable qu'avec les opérations add/set/replace" + msgid "print sizes in human readable format" msgstr "affiche les tailles dans un format humainement lisible" @@ -5961,8 +6103,8 @@ msgstr "" "'git config fetch.showForcedUpdates false' pour éviter cette vérification\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s n'a pas envoyé tous les objets nécessaires\n" +msgid "%s did not send all necessary objects" +msgstr "%s n'a pas envoyé tous les objets nécessaires" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -6001,8 +6143,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "la valeur \"%2$s\" de l'option \"%1$s\" est invalide pour %3$s" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "l'option \"%s\" est ignorée pour %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "l'option \"%s\" est ignorée pour %s" #, c-format msgid "%s is not a valid object" @@ -6307,6 +6449,9 @@ msgstr "config" msgid "config key storing a list of repository paths" msgstr "clé de config qui stocke la liste des chemins de dépôts" +msgid "keep going even if command fails in a repository" +msgstr "continuer mêm si la commande échoue dans un dépôt" + msgid "missing --config=<config>" msgstr "--config=<config> manquant" @@ -6678,6 +6823,9 @@ msgstr "être plus consciencieux (durée de traitement allongée)" msgid "enable auto-gc mode" msgstr "activer le mode auto-gc" +msgid "perform garbage collection in the background" +msgstr "réaliser le glanage de cellules en arrière plan" + msgid "force running gc even if there may be another gc running" msgstr "" "forcer le lancement du ramasse-miettes même si un autre ramasse-miettes " @@ -6778,6 +6926,9 @@ msgstr "la tâche '%s' ne peut pas être sélectionnée plusieurs fois" msgid "run tasks based on the state of the repository" msgstr "lancer les tâches selon l'état du dépôt" +msgid "perform maintenance in the background" +msgstr "réaliser la maintenance en arrière-plan" + msgid "frequency" msgstr "fréquence" @@ -7657,9 +7808,6 @@ msgstr "" msgid "Final output: %d %s\n" msgstr "Sortie finale : %d %s\n" -msgid "unable to create temporary object directory" -msgstr "impossible de créer un répertoire d'objets temporaire" - #, c-format msgid "git show %s: bad file" msgstr "git show %s : fichier incorrect" @@ -7788,8 +7936,11 @@ msgstr "marquer la série comme une Nième réédition" msgid "max length of output filename" msgstr "taille maximum du nom du fichier de sortie" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "utiliser [RFC PATCH] au lieu de [PATCH]" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "ajouter <rfc> (par défaut 'RFC') avant 'PATCH'" msgid "cover-from-description-mode" msgstr "cover-from-description-mode" @@ -8066,11 +8217,11 @@ msgstr "" "deduplicate, --eol" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--brances] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<clé>]\n" " [--symref] [<dépôt> [<motif>...]]" @@ -8086,8 +8237,11 @@ msgstr "chemin vers git-upload-pack sur le serveur distant" msgid "limit to tags" msgstr "limiter aux étiquettes" -msgid "limit to heads" -msgstr "limiter aux heads" +msgid "limit to branches" +msgstr "limiter aux branches" + +msgid "deprecated synonym for --branches" +msgstr "synonyme obsolète de --branches" msgid "do not show peeled tags" msgstr "ne pas afficher les étiquettes pelées" @@ -8240,15 +8394,6 @@ msgstr "utiliser une fusion basée sur diff3" msgid "use a zealous diff3 based merge" msgstr "utiliser une fusion basée sur un diff3 zélée" -msgid "for conflicts, use our version" -msgstr "pour les conflits, utiliser notre version (our)" - -msgid "for conflicts, use their version" -msgstr "pour les conflits, utiliser leur version (their)" - -msgid "for conflicts, use a union version" -msgstr "pour les conflits, utiliser l'ensemble des versions" - msgid "<algorithm>" msgstr "<algorithme>" @@ -8723,6 +8868,9 @@ msgstr "paquet à réutiliser lors du calcul de bitmap de multi-paquet" msgid "write multi-pack bitmap" msgstr "écriture du bitmap de multi-paquet" +msgid "write a new incremental MIDX" +msgstr "écrire un nouveau MIDX incrémental" + msgid "write multi-pack index containing only given indexes" msgstr "écrire l'index multi-paquet ne contenant que les index fournis" @@ -8938,10 +9086,6 @@ msgstr "git notes prune [<options>]" msgid "Write/edit the notes for the following object:" msgstr "Écrire/éditer les notes pour l'objet suivant :" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "impossible de démarrer 'show' pour l'objet '%s'" - msgid "could not read 'show' output" msgstr "impossible de lire la sortie de 'show'" @@ -10779,6 +10923,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +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 "missing --ref-format=<format>" +msgstr "--ref-format=<format> manquant" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "le dépôt utilise déjà le format '%s'" + +msgid "enable strict checking" +msgstr "activer une vérification plus strict" + +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' n'accepte aucun argument" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -11067,9 +11236,6 @@ msgstr "* distant %s" msgid " Fetch URL: %s" msgstr " URL de rapatriement : %s" -msgid "(no URL)" -msgstr "(pas d'URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -11078,6 +11244,9 @@ msgstr "(pas d'URL)" msgid " Push URL: %s" msgstr " URL push : %s" +msgid "(no URL)" +msgstr "(pas d'URL)" + #, c-format msgid " HEAD branch: %s" msgstr " Branche HEAD : %s" @@ -11187,10 +11356,6 @@ msgstr "interroger les URLs de poussée plutôt que les URLs de récupération" msgid "return all URLs" msgstr "retourner toutes les URLs" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "aucune URL configurée pour le dépôt distant '%s'" - msgid "manipulate push URLs" msgstr "manipuler les URLs push" @@ -12209,12 +12374,12 @@ msgstr "Algorithme d'empreinte inconnu" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<motif>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<motif>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -12237,11 +12402,11 @@ msgstr "la référence n'existe pas" msgid "failed to look up reference" msgstr "échec de la recherche de la référence" -msgid "only show tags (can be combined with heads)" -msgstr "afficher seulement les étiquettes (peut être combiné avec heads)" +msgid "only show tags (can be combined with --branches)" +msgstr "afficher seulement les étiquettes (peut être combiné avec --branches)" -msgid "only show heads (can be combined with tags)" -msgstr "afficher seulement les têtes (peut être combiné avec tags)" +msgid "only show branches (can be combined with --tags)" +msgstr "afficher seulement les branches (peut être combiné avec --tags)" msgid "check for reference existence without resolving" msgstr "vérifier l'existence de la référence sans la résoudre" @@ -12300,6 +12465,10 @@ msgid "failed to create directory for sparse-checkout file" msgstr "" "échec de la création du répertoire pour le fichier d'extraction clairsemée" +#, c-format +msgid "unable to fdopen %s" +msgstr "impossible d'ouvrir %s avec fdopen" + msgid "failed to initialize worktree config" msgstr "échec lors de l'initialisation de la configuration d'arbre de travail" @@ -12769,8 +12938,8 @@ msgid "couldn't hash object from '%s'" msgstr "impossible de calculer l'empreinte de l'objet depuis '%s'" #, c-format -msgid "unexpected mode %o\n" -msgstr "mode %o inattendu\n" +msgid "unexpected mode %o" +msgstr "mode %o inattendu" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "" @@ -12893,14 +13062,14 @@ msgstr "" "refus de créer/utiliser '%s' dans un répertoire git d'un autre sous-module" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "le clonage de '%s' dans le chemin de sous-module '%s' a échoué" - -#, c-format msgid "directory not empty: '%s'" msgstr "le répertoire n'est pas vide : '%s'" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "le clonage de '%s' dans le chemin de sous-module '%s' a échoué" + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "impossible de créer le répertoire de sous-module pour '%s'" @@ -13266,9 +13435,11 @@ msgstr "raison de la mise à jour" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <id-clé>] [-f] [-m <msg> | -F <fichier>] [-e]\n" +" [(--trailer <jeton>[(=|:)<valeur>)...]\n" " <nom-d-étiquette> [<commit> | <objet>]" msgid "git tag -d <tagname>..." @@ -14147,9 +14318,6 @@ msgstr "en-tête non reconnu : %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Le dépôt ne dispose pas des commits prérequis suivants :" -msgid "need a repository to verify a bundle" -msgstr "la vérification d'un colis requiert un dépôt" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14565,6 +14733,9 @@ msgstr "Recevoir ce qui est poussé dans le dépôt" msgid "Manage reflog information" msgstr "Gérer l'information de reflog" +msgid "Low-level access to refs" +msgstr "accès de bas-niveau aux réfs" + msgid "Manage set of tracked repositories" msgstr "Gérer un ensemble de dépôts suivis" @@ -14884,6 +15055,14 @@ msgstr "" "le tronçon d'étalement OID requis par le graphe de commits est manquant ou " "corrompu" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"désactivation des filtres de Bloom opur la couche de graphe de commits '%s' " +"à cause de réglages incompatibles" + msgid "commit-graph has no base graphs chunk" msgstr "le graphe de commit n'a pas de tronçon de graphes de base" @@ -15018,6 +15197,14 @@ msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "" "essai d'écriture de graphe de commits, mais 'core.commitGraph' est désactivé" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"essai d'écriture de graphe de commits, mais 'commitGraph." +"changedPathsVersion' (%d) n'est pas pris en charge" + msgid "too many commits to write graph" msgstr "trop de commits pour écrire un graphe" @@ -16931,19 +17118,23 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <chemin>] [-c <nom>=<valeur>]\n" " [--exec-path[=<chemin>]] [--html-path] [--man-path] [--info-" "path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<chemin>] [--work-tree=<chemin>] [--namespace=<nom>]\n" -" [--config-env=<nom>=<variable-d-environnement>] <commande> " -"[<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-" +"dir=<chemin>]\n" +" [--work-tree=<chemin>] [--namespace=<nom>] [--config-" +"env=<nom>=<var-d-env>] \n" +" <commande> [<args>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -17284,13 +17475,13 @@ msgstr "" "Vous pouvez désactiver cet avertissement avec `git config advice.ignoredHook " "false`." +msgid "not a git repository" +msgstr "pas un dépôt git" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "l'argument de --packfile doit être une empreinte valide ('%s' reçu)" -msgid "not a git repository" -msgstr "pas un dépôt git" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "" @@ -17302,6 +17493,9 @@ msgstr "La délégation de commande n'est pas supporté avec cuRL < 7.22.0" msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "L'épinglage de clé publique n'est pas supporté avec cuRL < 7.39.0" +msgid "Unknown value for http.proactiveauth" +msgstr "valeur inconnue pour http.proactiveauth" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE n'est pas supporté avec cuRL < 7.44.0" @@ -17319,6 +17513,12 @@ msgstr "" msgid "Could not set SSL backend to '%s': already set" msgstr "Impossible de spécifier le dorsal SSL à '%s' : déjà spécifié" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "refus de lire des cookies depuis http.cookiefile '-'" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "http.savecookies ignoré pour http.cookiefile vide" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17462,13 +17662,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Impossible de créer '%s.lock' : %s" +msgid "unable to create temporary object directory" +msgstr "impossible de créer un répertoire d'objets temporaire" + #, c-format msgid "could not write loose object index %s" msgstr "impossible d'écrire l'objet esseulé %s" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "Échec de l'écriture de l'index d'objet esseulé %s\n" +msgid "failed to write loose object index %s" +msgstr "Échec de l'écriture de l'index d'objet esseulé %s" #, c-format msgid "unexpected line: '%s'" @@ -17481,6 +17684,10 @@ msgid "quoted CRLF detected" msgstr "CRLF citées détectées" #, c-format +msgid "unable to format message: %s" +msgstr "impossible de formater le message : %s" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Échec de la fusion du sous-module %s (non extrait)" @@ -17493,8 +17700,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Échec de fusion du sous-module %s (commits non présents)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "erreur : échec de la fusion du sous-module %s (dépôt corrompu)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17526,12 +17733,13 @@ msgstr "" "existent :\n" "%s" -msgid "failed to execute internal merge" -msgstr "échec à l'exécution de la fusion interne" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "erreur : échec à l'exécution de la fusion interne pour %s" #, c-format -msgid "unable to add %s to database" -msgstr "impossible d'ajouter %s à la base de données" +msgid "error: unable to add %s to database" +msgstr "erreur : impossible d'ajouter %s à la base de données" #, c-format msgid "Auto-merging %s" @@ -17627,12 +17835,12 @@ msgstr "" "supprimé dans %s." #, c-format -msgid "cannot read object %s" -msgstr "impossible de lire l'objet %s" +msgid "error: cannot read object %s" +msgstr "erreur : impossible de lire l'objet %s" #, c-format -msgid "object %s is not a blob" -msgstr "l'objet %s n'est pas un blob" +msgid "error: object %s is not a blob" +msgstr "erreur : l'objet %s n'est pas un blob" #, c-format msgid "" @@ -17771,6 +17979,10 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "ne sait pas traiter %06o %s '%s'" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Avance rapide du sous-module %s au commit suivant :" @@ -17810,6 +18022,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "Échec de fusion du sous-module %s (plusieurs fusions trouvées)" +msgid "failed to execute internal merge" +msgstr "échec à l'exécution de la fusion interne" + +#, c-format +msgid "unable to add %s to database" +msgstr "impossible d'ajouter %s à la base de données" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -17910,6 +18129,14 @@ msgstr "" "CONFLIT (renommage/renommage) : renommage du répertoire %s->%s dans %s. " "Renommage de répertoire %s->%s dans %s" +#, c-format +msgid "cannot read object %s" +msgstr "impossible de lire l'objet %s" + +#, c-format +msgid "object %s is not a blob" +msgstr "l'objet %s n'est pas un blob" + msgid "modify" msgstr "modification" @@ -17993,10 +18220,6 @@ msgstr "impossible d'analyser la ligne : %s" msgid "malformed line: %s" msgstr "ligne malformée : %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"index multi-paquet existant ignoré ; non-concordance de la somme de contrôle" - msgid "could not load pack" msgstr "impossible de charger le paquet" @@ -18004,6 +18227,21 @@ msgstr "impossible de charger le paquet" msgid "could not open index for %s" msgstr "impossible d'ouvrir l'index pour %s" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "impossible de lier '%s' à '%s'" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "échec du nettoyage de l'index de multi-paquet à %s" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "impossible d'écrire un MIDX incrémental avec des bitmap" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"index multi-paquet existant ignoré ; non-concordance de la somme de contrôle" + msgid "Adding packfiles to multi-pack-index" msgstr "Ajout de fichiers paquet à un index multi-paquet" @@ -18029,18 +18267,34 @@ msgstr "aucun fichier paquet à l'index." msgid "refusing to write multi-pack .bitmap without any objects" msgstr "refus d'écrire le .bitmap multi-paquet sans aucun objet" +msgid "unable to create temporary MIDX layer" +msgstr "impossible de créer une couche MIDX temporaire" + msgid "could not write multi-pack bitmap" msgstr "impossible d'écrire le bitmap multi-paquet" +msgid "unable to open multi-pack-index chain file" +msgstr "impossible d'ouvrir le fichier d'index multi-paquet" + +msgid "unable to rename new multi-pack-index layer" +msgstr "impossible d'écrire la nouvelle couche de l'index multi-paquet" + msgid "could not write multi-pack-index" msgstr "échec de l'écriture de l'index de multi-paquet" +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "" +"impossible d'expirer les paquets dpuis un index multi-paquet incrémental" + msgid "Counting referenced objects" msgstr "Comptage des objets référencés" msgid "Finding and deleting unreferenced packfiles" msgstr "Recherche et effacement des fichiers paquets non-référencés" +msgid "cannot repack an incremental multi-pack-index" +msgstr "impossible de ré-empaqueter un index multi-paquet" + msgid "could not start pack-objects" msgstr "impossible de démarrer le groupement d'objets" @@ -18113,6 +18367,28 @@ msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "" "index multi-paquet les noms de paquets sont en désordre : '%s' avant '%s'" +msgid "multi-pack-index chain file too small" +msgstr "le fichier de chaîne d'index multi-paquet est trop petit" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "nombre de paquets dans la base MIDX trop haut : %<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "nombre d'objets dans la base MIDX trop haut : %<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "" +"chaîne d'index multi-paquet invalide : la ligne '%s' n'est pas une empreinte" + +msgid "unable to find all multi-pack index files" +msgstr "impossible de trouver tous les fichiers d'index multi-paquet" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "position d'objet MIDX invalide. MIDX est vraisemblablement corrompu" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "mauvais pack-int-id : %u (%u paquets au total)" @@ -18131,10 +18407,6 @@ msgstr "" msgid "multi-pack-index large offset out of bounds" msgstr "le grand décalage de l'index-multi-paquet est hors limite" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "échec du nettoyage de l'index de multi-paquet à %s" - msgid "multi-pack-index file exists, but failed to parse" msgstr "le fichier d'index multi-paquet existe mais n'a pu être analysé" @@ -18344,6 +18616,14 @@ msgid "missing mapping of %s to %s" msgstr "correspondance manquante entre %s et %s" #, c-format +msgid "unable to open %s" +msgstr "impossible d'ouvrir %s" + +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "les fichiers '%s' et '%s' diffèrent par leur contenu" + +#, c-format msgid "unable to write file %s" msgstr "impossible d'écrire le fichier %s" @@ -18429,10 +18709,6 @@ msgid "%s is not a valid '%s' object" msgstr "%s n'est pas un objet '%s' valide" #, c-format -msgid "unable to open %s" -msgstr "impossible d'ouvrir %s" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "incohérence de hachage pour %s (%s attendu)" @@ -18628,6 +18904,17 @@ msgstr "impossible d'analyser l'objet : %s" msgid "hash mismatch %s" msgstr "incohérence de hachage %s" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "entrée dupliquée dans l'index en bitmap : '%s'" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "essai de stockage d'un commit non-sélectionné : '%s'" + +msgid "too many pseudo-merges" +msgstr "trop de pseudo-fusions" + msgid "trying to write commit not in index" msgstr "échec de l'écriture de l'objet commit absent de l'index" @@ -18654,6 +18941,20 @@ msgstr "" "fichier d'index en bitmap corrompu (trop court pour correspondre à une table " "de recherche)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"fichier d'index en bitmap corrompu (trop court pour correspondre à un entête " +"de table de pseudo-fusion)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"fichier d'index en bitmap corrompu (trop court pour correspondre à une table " +"de pseudo-fusion)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "fichier d'index en bitmap corrompu, table de pseudo-fusion trop courte" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "entrée dupliquée dans l'index en bitmap : '%s'" @@ -18713,6 +19014,9 @@ msgstr "bitmap ewah corrompue : entête tronqué pour la bitmap du commit '%s'" msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "impossible de charger le paquet : '%s', pack-reuse désactivé" +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "impossible de calculer le paquet préféré, pack-reuse désactivé" + #, c-format msgid "object '%s' not found in type bitmaps" msgstr "objet '%s' non trouvé dans les bitmaps de type" @@ -18743,6 +19047,10 @@ msgid "mismatch in bitmap results" msgstr "décalage dans le résultats de bitmap" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "l'index de pseudo-fusion est hors-limite (%<PRIu32> ≥ %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "impossible de trouver '%s' dans le paquet '%s' à l'offset %<PRIuMAX>" @@ -19115,6 +19423,11 @@ msgstr "impossible de créer le lstat en fil : %s" msgid "unable to parse --pretty format" msgstr "impossible d'analyser le format --pretty" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "" +"récupération paresseuse désactivée ; certains objets pourraient ne pas être " +"disponibles" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "" "promisor-remote : impossible de créer un sous-processus de récupération" @@ -19142,6 +19455,68 @@ msgstr "object-info : vidage attendu après les arguments" msgid "Removing duplicate objects" msgstr "Suppression des objets dupliqués" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "impossible de charger la regex de pseudo-fusion pour %s : '%s'" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s doit être non négatif, utilisation de la valeur par défaut" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s doit valoir entre 0 et 1, utilisation de la valeur par défaut" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s doit être positif, utilisation de la valeur par défaut" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "le groupe de pseudo-fusion '%s' n'a pas de motif requis" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"le group de pseudo-fusion '%s' a un seuil instable avec un seuil stable" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"l'expression rationnelle de pseudo-fusion a trop de groupes de capture " +"(max=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"la lecture de la pseudo-fusion étendue est hors-limite " +"(%<PRIuMAX>=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"l'entrée de pseudo-fusion étendue est trop courte (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"impossible de trouver la pseudo-fusion pour le commit '%s' à l'offset " +"%<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "recherche de pseudo-fusion étendue hors-limite (%<PRIu32> ≥ %<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "lecture hors-limite : (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "" +"impossible de lire la table de pseudo-fusions étendues pour le commit %s" + msgid "could not start `log`" msgstr "impossible de démarrer `log`" @@ -19577,6 +19952,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "format attendu : %%(ahead-behind:<commit-esque>)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "format attendu : %%(is-base:<commit-esque>)" + +#, c-format msgid "malformed field name: %.*s" msgstr "nom de champ malformé %.*s" @@ -19749,11 +20128,18 @@ msgstr "le journal pour la réf %s s'arrête de manière inattendue sur %s" msgid "log for %s is empty" msgstr "le journal pour la réf %s est vide" +msgid "refusing to force and skip creation of reflog" +msgstr "refus de forcer et sauter la création du reflog" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "refus de mettre à jour une réf avec un nom cassé '%s'" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "refus de mettre à jour la pseudo-réf '%s'" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "échec de update_ref pour la réf '%s' : %s" @@ -19784,6 +20170,33 @@ msgid "could not delete references: %s" msgstr "impossible de supprimer les références : %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "" +"Migration simulée des réfs terminée, le résultat peut être trouvé à '%s'\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "impossible de supprimer le répetoire de migration temporaire '%s'" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "les références migrées peuvent être trouvées dans '%s'" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"impossible de vérrouiller '%s' : symref attendu avec la cible '%s', mais réf " +"normale trouvée" + +#, c-format +msgid "cannot open directory %s" +msgstr "impossible d'ouvrir le répertoire %s" + +msgid "Checking references consistency" +msgstr "Vérification de la cohérence des références" + +#, c-format msgid "refname is dangerous: %s" msgstr "le nom de réference est dangereux : %s" @@ -20434,13 +20847,17 @@ msgstr "ne télécharger les méta-données que pour la branche qui sera extrait msgid "create repository within 'src' directory" msgstr "Créer un dépôt dans le repertoire 'src'" +msgid "specify if tags should be fetched during clone" +msgstr "" +"spécifier si les étiquettes devraient être récupérées pendant le clonage" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <branche-principale>] [--full-" "clone]\n" -"\t[--[no-]src] <url> [<enrôlement>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enrôlement>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -20459,6 +20876,10 @@ msgid "could not configure remote in '%s'" msgstr "impossible de paramétrer le distant dans '%s'" #, c-format +msgid "could not disable tags in '%s'" +msgstr "impossible de désactiver les étiquettes dans '%s'" + +#, c-format msgid "could not configure '%s'" msgstr "impossible de configurer '%s'" @@ -20963,6 +21384,49 @@ msgstr "" "heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' n'accepte pas de commit de fusion" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick' n'accepte pas de commit de fusion. Si vous voulez\n" +"rejouer la fusion, utilisez 'merge -C' sur le commit." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword' n'accepte pas de commit de fusion.\n" +"Si vous vouliez rejouer la fusion et la reformuler,\n" +"utilisez 'merge -c' sur le commit" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'edit' n'accepte pas de commit de fusion. Si vous vouliez\n" +"rejouer la fusion, utilisez 'merge -C' sur le commit, puis\n" +"'break' pour vous redonner le contrôle pour pouvoir faire\n" +"'git commit --amend && git rebase --continue'." + +msgid "cannot squash merge commit into another commit" +msgstr "impossible d'écraser un commit de fusion avec un autre commit" + +#, c-format msgid "invalid command '%.*s'" msgstr "commande '%.*s' invalide" @@ -21079,9 +21543,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "impossible de lire HEAD" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "impossible de copier '%s' vers '%s'" +msgid "could not write commit message file" +msgstr "impossible d'écrire le fichier de message de validation" #, c-format msgid "" @@ -21487,6 +21950,22 @@ msgstr "impossible de revenir au répertoire de travail courant" msgid "failed to stat '%*s%s%s'" msgstr "échec du stat de '%*s%s%s'" +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' n'est pas absolu" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"propriétaire douteux détecté dans le dépôt à '%s'\n" +"%sPour ajouter une exception pour ce dépôt, lancez :\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Impossible d'accéder au répertoire de travail courant" @@ -21509,18 +21988,6 @@ msgstr "" "n'est pas défini)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"propriétaire douteux détecté dans le dépôt à '%s'\n" -"%sPour ajouter une exception pour ce dépôt, lancez :\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "impossible d'utiliser le dépôt nu '%s' (safe.bareRepository vaut '%s')" @@ -21830,6 +22297,16 @@ msgstr "" "'%.*s'" #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"'%.*s' dans le chemin du sous-module '%s' ne devait pas être un lien " +"symbolique" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "le chemin du sous-module '%s' ne devait pas être un lien symbolique" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -21868,10 +22345,6 @@ msgstr "échec du lstat de '%s'" msgid "no remote configured to get bundle URIs from" msgstr "aucun distant configuré depuis lequel récupérer des URIs de colis" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "le distant '%s' n'a pas d'URL configuré" - msgid "could not get the bundle-uri list" msgstr "impossible d'avoir la liste de bundle-uris" @@ -21956,6 +22429,25 @@ msgstr "jeton" msgid "command token to send to the server" msgstr "jeton de commande à envoyer au serveur" +msgid "unit-test [<options>]" +msgstr "unit-test [<options>]" + +msgid "immediately exit upon the first failed test" +msgstr "sortir immédiatement sur le premier échec" + +msgid "suite[::test]" +msgstr "suite[::test]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "" +"lancer seulement la suite de test ou le test individuel <suite[::test]>" + +msgid "suite" +msgstr "suite" + +msgid "exclude test suite <suite>" +msgstr "exclure la suite de tests <suite>" + #, c-format msgid "running trailer command '%s' failed" msgstr "échec de la commande trailer '%s'" @@ -23162,6 +23654,9 @@ msgstr "'%s.final' contient le courriel composé.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases est incompatible avec d'autres options\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases et --translate-aliases sont mutuellement exclusifs.\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -23374,24 +23869,24 @@ msgid "Failed to send %s\n" msgstr "Échec de l'envoi de %s\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Envoi simulé de %s\n" +msgid "Dry-Sent %s" +msgstr "Envoi simulé de %s" #, perl-format -msgid "Sent %s\n" -msgstr "%s envoyé\n" +msgid "Sent %s" +msgstr "%s envoyé" -msgid "Dry-OK. Log says:\n" -msgstr "Simulation OK. Le journal indique :\n" +msgid "Dry-OK. Log says:" +msgstr "Simulation OK. Le journal indique :" -msgid "OK. Log says:\n" -msgstr "OK. Le journal indique :\n" +msgid "OK. Log says:" +msgstr "OK. Le journal indique :" msgid "Result: " msgstr "Résultat : " -msgid "Result: OK\n" -msgstr "Résultat : OK\n" +msgid "Result: OK" +msgstr "Résultat : OK" #, perl-format msgid "can't open file %s" @@ -23466,6 +23961,41 @@ msgstr "%s sauté avec un suffix de sauvegarde '%s'.\n" msgid "Do you really want to send %s? [y|N]: " msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " +#~ msgid "revision walk setup failed\n" +#~ msgstr "échec de la préparation du parcours des révisions\n" + +#, c-format +#~ msgid "unable to parse contact: %s" +#~ msgstr "impossible d'analyser le contact : %s" + +#, c-format +#~ msgid "truncating .rej filename to %.*s.rej" +#~ msgstr "troncature du nom de fichier .rej en %.*s.rej" + +#~ msgid "" +#~ "the add.interactive.useBuiltin setting has been removed!\n" +#~ "See its entry in 'git help config' for details." +#~ msgstr "" +#~ "le réglage add.interactive.useBuiltin a été supprimé !\n" +#~ "Référez-vous à cette entrée dans 'git help config' pour plus de détails." + +#~ msgid "git archive: Remote with no URL" +#~ msgstr "git archive : Dépôt distant sans URL" + +#~ msgid "only one action at a time" +#~ msgstr "une seule action à la fois" + +#~ msgid "use [RFC PATCH] instead of [PATCH]" +#~ msgstr "utiliser [RFC PATCH] au lieu de [PATCH]" + +#, c-format +#~ msgid "no URLs configured for remote '%s'" +#~ msgstr "aucune URL configurée pour le dépôt distant '%s'" + +#, c-format +#~ msgid "remote '%s' has no configured URL" +#~ msgstr "le distant '%s' n'a pas d'URL configuré" + #~ msgid "" #~ "Use -f if you really want to add them.\n" #~ "Turn this message off by running\n" @@ -23509,9 +24039,6 @@ msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #~ msgid "core.commentChar should only be one ASCII character" #~ msgstr "core.commentChar ne devrait être qu'un unique caractère ASCII" -#~ msgid "-x and -X cannot be used together" -#~ msgstr "-x et -X ne peuvent pas être utilisés ensemble" - #~ msgid "" #~ "--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-" #~ "exclude" @@ -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-04-25 18:57+0000\n" -"PO-Revision-Date: 2024-04-26 15:33+0700\n" +"POT-Creation-Date: 2024-10-04 08:33+0700\n" +"PO-Revision-Date: 2024-10-04 08:52+0700\n" "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n" "Language-Team: Indonesian\n" "Language: id\n" @@ -104,12 +104,12 @@ msgstr[1] "%d jalur ditambahkan\n" msgid "ignoring unmerged: %s" msgstr "mengabaikan tak tergabung: %s" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "Only binary files changed.\n" msgstr "Hanya berkas biner yang berubah.\n" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "No changes.\n" msgstr "Tidak ada perubahan.\n" @@ -651,21 +651,28 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" -"j - biarkan bingkah ini, lihat bingkah berikutnya yang belum diputuskan\n" -"J - biarkan bingkah ini, lihat bingkah berikutnya\n" -"k - biarkan bingkah ini, lihat bingkah sebelumnya yang belum diputuskan\n" -"K - biarkan bingkah ini, lihat bingkah sebelumnya\n" +"j - biarkan bingkah ini tak diputuskan, lihat bingkah berikutnya yang belum " +"diputuskan\n" +"J - biarkan bingkah ini tak diputuskan, lihat bingkah berikutnya\n" +"k - biarkan bingkah ini tak diputuskan, lihat bingkah sebelumnya yang belum " +"diputuskan\n" +"K - biarkan bingkah ini tak diputuskan, lihat bingkah sebelumnya\n" "g - pilih satu bingkah untuk dikunjungi\n" "/ - cari satu bingkah yang cocok dengan regex yang diberikan\n" "s - belah bingkah saat ini ke dalam bingkah yang lebih kecil\n" "e - sunting bingkah saat ini secara manual\n" -"p - lihat bingkah saat ini\n" +"p - lihat bingkah saat ini, 'P' untuk menggunakan pager\n" "? - lihat bantuan\n" #: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Hanya satu huruf yang diharapkan, dapat '%s'" + +#: add-patch.c msgid "No previous hunk" msgstr "Tidak ada bingkah sebelumnya" @@ -728,9 +735,22 @@ msgid "Sorry, cannot edit this hunk" msgstr "Maaf, tidak dapat menyunting bingkah ini" #: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Perintah tidak dikenal '%s' (gunakan '?' untuk bantuan)" + +#: add-patch.c msgid "'git apply' failed" msgstr "'git apply' gagal" +#: add-patch.c +msgid "No changes." +msgstr "Tidak ada perubahan." + +#: add-patch.c +msgid "Only binary files changed." +msgstr "Hanya berkas biner yang berubah." + #: advice.c #, c-format msgid "" @@ -911,7 +931,7 @@ msgid "unclosed quote" msgstr "tanda kutip tak ditutup" #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c -#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c msgid "too many arguments" msgstr "terlalu banyak argumen" @@ -1484,6 +1504,18 @@ msgstr "juga terapkan tambalan (gunakan dengan --stat/--summary/--check)" msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "coba penggabungan tiga arah, mundur ke penambalan normal jika gagal" +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "untuk konflik, gunakan versi kami" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "untuk konflik, gunakan versi mereka" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "untuk konflik, gunakan versi bersatu" + #: apply.c msgid "build a temporary index based on embedded index information" msgstr "bangun sebuah indeks sementara berdasarkan informasi indeks tertanam" @@ -1545,6 +1577,10 @@ msgstr "tambahkan <akar> di depan semua nama berkas" msgid "don't return error for empty patches" msgstr "jangan kembalikan kesalahan untuk tambalan kosong" +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs, dan --union memerlukan --3way" + #: archive-tar.c archive-zip.c #, c-format msgid "cannot stream blob %s" @@ -1634,6 +1670,10 @@ msgstr "bukan nama objek valid: %s" msgid "not a tree object: %s" msgstr "bukan objek pohon: %s" +#: archive.c builtin/clone.c +msgid "unable to checkout working tree" +msgstr "tidak dapat men-checkout pohon kerja" + #: archive.c #, c-format msgid "File not found: %s" @@ -1750,7 +1790,7 @@ msgstr "opsi `%s' butuh '%s'" msgid "Unexpected option --output" msgstr "Opsi --output tak diharapkan" -#: archive.c +#: archive.c t/unit-tests/unit-test.c #, c-format msgid "extra command line parameter '%s'" msgstr "parameter konfigurasi tambahan: '%s'" @@ -1808,6 +1848,11 @@ msgid "ignoring overly large gitattributes blob '%s'" msgstr "mengabaikan blob gitattributes '%s' yang terlalu besar" #: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "" +"tidak dapat menggunakan --attr-source atau GIT_ATTR_SOURCE tanpa repositori" + +#: attr.c msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "--attr-source atau GIT_ATTR_SOURCE jelek" @@ -1817,7 +1862,7 @@ msgid "unable to stat '%s'" msgstr "tidak dapat men-stat '%s'" #: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c -#: builtin/pack-objects.c combine-diff.c rerere.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c #, c-format msgid "unable to read %s" msgstr "tidak dapat membaca %s" @@ -1955,7 +2000,7 @@ msgid "--reverse and --first-parent together require specified latest commit" msgstr "" "--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan" -#: blame.c builtin/commit.c builtin/log.c builtin/merge.c +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c #: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c #: remote.c sequencer.c submodule.c msgid "revision walk setup failed" @@ -2183,14 +2228,6 @@ msgid "Unstaged changes after refreshing the index:" msgstr "Perubahan tak tergelar setelah menyegarkan indeks:" #: builtin/add.c -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"setelan add.interactive.useBuiltin sudah dihapus!\n" -"Selengkapnya lihat entrinya di 'git help config'." - -#: builtin/add.c msgid "could not read the index" msgstr "tidak dapat membaca indeks" @@ -2224,7 +2261,7 @@ msgstr "latihan" #: builtin/add.c builtin/check-ignore.c builtin/commit.c #: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c -#: builtin/read-tree.c +#: builtin/read-tree.c builtin/refs.c msgid "be verbose" msgstr "jadi berkata-kata" @@ -2644,7 +2681,7 @@ msgstr "" "Sepertinya Anda telah memindahkan HEAD sejak kegagalan 'am' terakhir.\n" "Tidak memutar ulang ke ORIG_HEAD" -#: builtin/am.c builtin/bisect.c worktree.c +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c #, c-format msgid "failed to read '%s'" msgstr "gagal membaca '%s'" @@ -2722,8 +2759,8 @@ msgstr "n" #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c -#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c -#: builtin/verify-tag.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c msgid "format" msgstr "format" @@ -2760,6 +2797,10 @@ msgid "show the patch being applied" msgstr "perlihatkan tambalan yang diterapkan" #: builtin/am.c +msgid "try to apply current patch again" +msgstr "coba terapkan lagi tambalan saat ini" + +#: builtin/am.c msgid "record the empty patch as an empty commit" msgstr "rekam tambalan kosong sebagai komit kosong" @@ -2832,10 +2873,6 @@ msgid "could not redirect output" msgstr "tidak dapat mengalihkan keluaran" #: builtin/archive.c -msgid "git archive: Remote with no URL" -msgstr "git archive: Remote tanpa URL" - -#: builtin/archive.c msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: ACK/NAK diharapkan, dapat paket bilasan" @@ -3022,10 +3059,6 @@ msgstr "" "Opsi yang didukung adalah: --term-good|--term-old dan --term-bad|--term-new." #: builtin/bisect.c -msgid "revision walk setup failed\n" -msgstr "setup jalan revisi gagal\n" - -#: builtin/bisect.c #, c-format msgid "could not open '%s' for appending" msgstr "tidak dapat membuka '%s' untuk menambahkan" @@ -3960,6 +3993,10 @@ msgstr "Perlu sebuah repositori untuk membuat bundel." msgid "do not show bundle details" msgstr "jangan perlihatkan detail bundel" +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "perlu sebuah repositori untuk verifikasi bundel" + #: builtin/bundle.c #, c-format msgid "%s is okay\n" @@ -4263,9 +4300,16 @@ msgid "also read contacts from stdin" msgstr "juga baca kontak dari masukan standar" #: builtin/check-mailmap.c -#, c-format -msgid "unable to parse contact: %s" -msgstr "tidak dapat menguraikan kontak: %s" +msgid "read additional mailmap entries from file" +msgstr "baca entri mailmap tambahan dari berkas" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "blob" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "baca entri mailmap tambahan dari blob" #: builtin/check-mailmap.c msgid "no contacts specified" @@ -4692,6 +4736,11 @@ msgstr "'%s' tidak dapat digunakan dengan mengganti cabang" #: builtin/checkout.c #, c-format +msgid "'%s' needs the paths to check out" +msgstr "'%s' butuh jalur untuk di-checkout" + +#: builtin/checkout.c +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s' tidak dapat digunakan dengan '%s'" @@ -5018,9 +5067,9 @@ msgstr "pembersihan interaktif" msgid "remove whole directories" msgstr "hapus keseluruhan direktori" -#: builtin/clean.c builtin/describe.c builtin/grep.c builtin/log.c -#: builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c builtin/show-ref.c -#: ref-filter.h +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h msgid "pattern" msgstr "pola" @@ -5159,7 +5208,7 @@ msgstr "direktori git" msgid "separate git dir from working tree" msgstr "pisahkan direktori git dari pohon kerja" -#: builtin/clone.c builtin/init-db.c +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c msgid "specify the reference format to use" msgstr "sebutkan format referensi untuk digunakan" @@ -5239,6 +5288,16 @@ 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'" @@ -5247,7 +5306,7 @@ msgstr "gagal membuat tautan '%s'" msgid "failed to copy file to '%s'" msgstr "gagal menyalin berkas ke '%s'" -#: builtin/clone.c +#: builtin/clone.c refs/files-backend.c #, c-format msgid "failed to iterate over '%s'" msgstr "gagal iterasi pada '%s'" @@ -5290,10 +5349,6 @@ 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" @@ -5313,7 +5368,8 @@ msgstr "Terlalu banyak argumen." msgid "You must specify a repository to clone." msgstr "Anda harus sebutkan repositori untuk diklon." -#: builtin/clone.c builtin/init-db.c setup.c +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c #, c-format msgid "unknown ref storage format '%s'" msgstr "format penyimpanan referensi tidak dikenal '%s'" @@ -5658,7 +5714,7 @@ msgstr "git commit-tree: gagal membaca" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -5668,7 +5724,7 @@ msgid "" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <komit> | --fixup [(amend|" -"reword):]<komit>)]\n" +"reword):]<komit>]\n" " [-F <berkas> | -m <pesan>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--" "author=<pengarang>]\n" @@ -5936,7 +5992,7 @@ msgstr "%sPengkomit: %.*s <%.*s>" msgid "Cannot read index" msgstr "Tidak dapat membaca indeks" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "unable to pass trailers to --trailers" msgstr "tidak dapat melewatkan trailer ke --trailers" @@ -6152,11 +6208,11 @@ msgstr "gunakan pesan terformat autosquash untuk lumat komit tersebut" msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "komit sekarang dikarang olehku (gunakan dengan -C/-c/--amend)" -#: builtin/commit.c builtin/interpret-trailers.c +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c msgid "trailer" msgstr "trailer" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "add custom trailer(s)" msgstr "tambahkan trailer kustom" @@ -6269,17 +6325,66 @@ msgstr "" "tidak terlampaui, lalu \"git restore --staged :/\" untuk pulihkan." #: builtin/config.c -msgid "git config [<options>]" -msgstr "git config [<opsi>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<opsi berkas>] [<opsi tampilan>] [--includes]" #: builtin/config.c -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "argumen --type tidak dikenal %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<opsi berkas>] [<opsi tampilan>] [--includes] [--all] [--" +"regexp] [--value=<nilai>] [--fixed-value] [--default=<default>] <nama>" #: builtin/config.c -msgid "only one type at a time" -msgstr "hanya satu tipe pada suatu saat" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<opsi berkas>] [--type=<tipe>] [--all] [--value=<nilai>] [--" +"fixed-value] <nama> <nilai>" + +#: builtin/config.c +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<opsi berkas] [--all] [--value=<nilai>] [--fixed-value] " +"<nama> <nilai>" + +#: builtin/config.c +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<opsi berkas>] <nama lama> <nama baru>" + +#: builtin/config.c +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<opsi berkas>] <nama>" + +#: builtin/config.c +msgid "git config edit [<file-option>]" +msgstr "git config edit [<opsi berkas>]" + +#: builtin/config.c +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<opsi berkas>] --get-colorbool <nama> [<stdout-is-tty>]" + +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<opsi berkas>] [<opsi tampilan] [--includes] [--all] [--" +"regexp=<regexp> [--value=<nilai>] [--fixed-value] [--default=<default>] " +"<nama>" + +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<opsi berkas>] [--type=<tipe>] [--comment=<pesan>] [--all] " +"[--value=<nilai>] [--fixed-value] <nama> <nilai>" #: builtin/config.c msgid "Config file location" @@ -6314,70 +6419,6 @@ msgid "read config from given blob object" msgstr "baca konfigurasi dari objek blob yang diberikan" #: builtin/config.c -msgid "Action" -msgstr "Tindakan" - -#: builtin/config.c -msgid "get value: name [value-pattern]" -msgstr "dapatkan nilai: name [pola nilai]" - -#: builtin/config.c -msgid "get all values: key [value-pattern]" -msgstr "dapatkan semua nilai: key [pola nilai]" - -#: builtin/config.c -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "dapatkan nilai dari regexp: name-regex [pola nilai]" - -#: builtin/config.c -msgid "get value specific for the URL: section[.var] URL" -msgstr "dapatkan nilai spesifik untuk URL: section[.var] URL" - -#: builtin/config.c -msgid "replace all matching variables: name value [value-pattern]" -msgstr "ganti semua variabel yang cocok: name value [pola nilai]" - -#: builtin/config.c -msgid "add a new variable: name value" -msgstr "tambahkan variabel baru: name value" - -#: builtin/config.c -msgid "remove a variable: name [value-pattern]" -msgstr "hapus variabel: name [pola nilai]" - -#: builtin/config.c -msgid "remove all matches: name [value-pattern]" -msgstr "hapus semua cocokan: name [pola nilai]" - -#: builtin/config.c -msgid "rename section: old-name new-name" -msgstr "ganti nama bagian: old-name new-name" - -#: builtin/config.c -msgid "remove a section: name" -msgstr "hapus bagian: name" - -#: builtin/config.c -msgid "list all" -msgstr "daftar semua" - -#: builtin/config.c -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "gunakan kesamaan untai ketika membandingkan nilai ke 'pola nilai'" - -#: builtin/config.c -msgid "open an editor" -msgstr "buka penyunting" - -#: builtin/config.c -msgid "find the color configured: slot [default]" -msgstr "temukan warna terkonfigurasi: slot [asali]" - -#: builtin/config.c -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "temukan setelan warna: slot [stdout-is-tty]" - -#: builtin/config.c msgid "Type" msgstr "Tipe" @@ -6414,8 +6455,8 @@ msgid "value is an expiry date" msgstr "nilai adalah tanggal kadaluarsa" #: builtin/config.c -msgid "Other" -msgstr "Lainnya" +msgid "Display options" +msgstr "Tampilkan opsi" #: builtin/config.c msgid "terminate values with NUL byte" @@ -6426,10 +6467,6 @@ msgid "show variable names only" msgstr "perlihatkan hanya nama variabel" #: builtin/config.c -msgid "respect include directives on lookup" -msgstr "segani arahan masukkan pada pencarian" - -#: builtin/config.c msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "perlihatkan asal konfigurasi (berkas, masukan standar, blob, baris perintah)" @@ -6441,17 +6478,17 @@ msgstr "" "perintah)" #: builtin/config.c -msgid "value" -msgstr "nilai" +msgid "show config keys in addition to their values" +msgstr "perlihatkan kunci opsi beserta nilainya" #: builtin/config.c -msgid "with --get, use default value when missing entry" -msgstr "dengan --get, gunakan nilai asali ketika kehilangan entri" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "argumen --type tidak dikenal %s" #: builtin/config.c -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "" -"untai komentar yang dapat dibaca manusia (# akan ditambahkan bila diperlukan" +msgid "only one type at a time" +msgstr "hanya satu tipe pada suatu saat" #: builtin/config.c #, c-format @@ -6545,60 +6582,94 @@ msgstr "" "\"CONFIGURATION FILE\" di \"git help worktree\" untuk selengkapnya" #: builtin/config.c -msgid "--get-color and variable type are incoherent" -msgstr "--get-color dan tipe variabel raban" +msgid "Other" +msgstr "Lainnya" #: builtin/config.c -msgid "only one action at a time" -msgstr "hanya satu tindakan pada suatu saat" +msgid "respect include directives on lookup" +msgstr "segani arahan masukkan pada pencarian" #: builtin/config.c -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only hanya dapat diterapkan pada --list atau --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "tidak dapat membaca berkas konfigurasi '%s'" #: builtin/config.c -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"--show-origin hanya dapat diterapkan pada --get, --get-all, --get-regexp, " -"dan --list" +msgid "error processing config file(s)" +msgstr "kesalahan memproses berkas konfigurasi" #: builtin/config.c -msgid "--default is only applicable to --get" -msgstr "--default hanya dapat diterapkan pada --get" +msgid "Filter options" +msgstr "Opsi penyaringan" #: builtin/config.c -msgid "--comment is only applicable to add/set/replace operations" -msgstr "" -"--comment hanya dapat diterapkan pada operasi penambahan/penyetelan/" -"penggantian" +msgid "return all values for multi-valued config options" +msgstr "dapatkan semua nilai untuk opsi konfigurasi multi-nilai" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "tafsirkan nama sebagai ekspresi reguler" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "perlihatkan konfigurasi dengan nilai yang cocok dengan pola" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" +msgstr "gunakan kesamaan untai ketika membandingkan nilai dan pola nilai" + +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "perlihatkan konfigurasi yang cocok dengan URL yang diberikan" + +#: builtin/config.c +msgid "value" +msgstr "nilai" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "gunakan nilai asali ketika entri hilang" #: builtin/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value hanya diterapkan dengan 'pola nilai'" #: builtin/config.c -#, c-format -msgid "unable to read config file '%s'" -msgstr "tidak dapat membaca berkas konfigurasi '%s'" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= tidak dapat digunakan dengan --all atau --url=" #: builtin/config.c -msgid "error processing config file(s)" -msgstr "kesalahan memproses berkas konfigurasi" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= tidak dapat digunakan dengan --all, --regexp atau --value" #: builtin/config.c -msgid "editing stdin is not supported" -msgstr "menyunting stdin tidak didukung" +msgid "Filter" +msgstr "Penyaring" #: builtin/config.c -msgid "editing blobs is not supported" -msgstr "menyunting blob tidak didukung" +msgid "replace multi-valued config option with new value" +msgstr "ganti opsi konfigurasi multi-nilai dengan nilai baru" #: builtin/config.c -#, c-format -msgid "cannot create configuration file %s" -msgstr "tidak dapat membuat berkas konfigurasi %s" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"untai komentar yang dapat dibaca manusia (# akan ditambahkan bila diperlukan" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "tambahkan baris baru tanpa mengubah nilai yang ada" + +#: builtin/config.c +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value hanya diterapkan dengan --value=<pola>" + +#: builtin/config.c +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append tidak dapat digunakan dengan --value=<pola>" #: builtin/config.c #, c-format @@ -6614,6 +6685,113 @@ msgstr "" msgid "no such section: %s" msgstr "tidak ada bagian seperti: %s" +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "menyunting stdin tidak didukung" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "menyunting blob tidak didukung" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "tidak dapat membuat berkas konfigurasi %s" + +#: builtin/config.c +msgid "Action" +msgstr "Tindakan" + +#: builtin/config.c +msgid "get value: name [<value-pattern>]" +msgstr "dapatkan nilai: name [<pola nilai>]" + +#: builtin/config.c +msgid "get all values: key [<value-pattern>]" +msgstr "dapatkan semua nilai: key [<pola nilai>]" + +#: builtin/config.c +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "dapatkan nilai dari ekspresi reguler: name-regex [<pola nilai>]" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "dapatkan nilai spesifik untuk URL: section[.var] URL" + +#: builtin/config.c +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "ganti semua variabel yang cocok: name value [<pola nilai>]" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "tambahkan variabel baru: name value" + +#: builtin/config.c +msgid "remove a variable: name [<value-pattern>]" +msgstr "hapus variabel: name [<pola nilai>]" + +#: builtin/config.c +msgid "remove all matches: name [<value-pattern>]" +msgstr "hapus semua cocokan: name [<pola nilai>]" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "ganti nama bagian: old-name new-name" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "hapus bagian: name" + +#: builtin/config.c +msgid "list all" +msgstr "daftar semua" + +#: builtin/config.c +msgid "open an editor" +msgstr "buka penyunting" + +#: builtin/config.c +msgid "find the color configured: slot [<default>]" +msgstr "temukan warna terkonfigurasi: slot [<asali>]" + +#: builtin/config.c +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "temukan setelan warna: slot [<stdout-is-tty>]" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "dengan --get, gunakan nilai asali ketika kehilangan entri" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "--get-color dan tipe variabel raban" + +#: builtin/config.c +msgid "no action specified" +msgstr "tidak ada tindakan yang dipilih" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only hanya dapat diterapkan pada --list atau --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin hanya dapat diterapkan pada --get, --get-all, --get-regexp, " +"dan --list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "--default hanya dapat diterapkan pada --get" + +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "" +"--comment hanya dapat diterapkan pada operasi penambahan/penyetelan/" +"penggantian" + #: builtin/count-objects.c msgid "print sizes in human readable format" msgstr "cetak ukuran dalam format yang bisa dibaca manusia" @@ -7229,8 +7407,8 @@ msgstr "" #: builtin/fetch.c #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s tidak mengirim semua objek yang diperlukan\n" +msgid "%s did not send all necessary objects" +msgstr "%s tidak mengirim semua objek yang diperlukan" #: builtin/fetch.c #, c-format @@ -7276,8 +7454,8 @@ msgstr "opsi \"%s\" nilai \"%s\" tidak valid untuk %s" #: builtin/fetch.c #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "opsi \"%s\" diabaikan untuk %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "opsi \"%s\" diabaikan untuk %s" #: builtin/fetch.c object-file.c #, c-format @@ -7662,6 +7840,10 @@ msgid "config key storing a list of repository paths" msgstr "kunci konfigurasi yang menampung daftar jalur repositori" #: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "tetap lanjut meski perintah gagal pada repositori" + +#: builtin/for-each-repo.c msgid "missing --config=<config>" msgstr "kehilangan --config=<config>" @@ -8130,6 +8312,10 @@ msgid "enable auto-gc mode" msgstr "aktifkan mode gc otomatis" #: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "lakukan pengumpulan sampah di latar belakang" + +#: builtin/gc.c msgid "force running gc even if there may be another gc running" msgstr "paksa jalankan gc bahkan jika mungkin ada gc lain yang berjalan" @@ -8250,6 +8436,10 @@ msgid "run tasks based on the state of the repository" msgstr "jalankan tugas berdasarkan keadaan repositori" #: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "lakukan pemeliharaan di latar belakang" + +#: builtin/gc.c msgid "frequency" msgstr "frekuensi" @@ -9356,10 +9546,6 @@ msgid "Final output: %d %s\n" msgstr "Keluaran terakhir: %d %s\n" #: builtin/log.c -msgid "unable to create temporary object directory" -msgstr "tidak dapat membuat direktori objek sementara" - -#: builtin/log.c #, c-format msgid "git show %s: bad file" msgstr "git show %s: berkas jelek" @@ -9518,8 +9704,12 @@ msgid "max length of output filename" msgstr "panjang nama berkas keluaran maksimum" #: builtin/log.c -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "gunakan [RFC PATCH] daripada [PATCH]" +msgid "rfc" +msgstr "rfc" + +#: builtin/log.c +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "tambahkan <rfc> (asali 'RFC') sebelum 'PATCH'" #: builtin/log.c msgid "cover-from-description-mode" @@ -9870,11 +10060,11 @@ msgstr "" #: builtin/ls-remote.c msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<kunci>]\n" " [--symref] [<repositori> [<pola>...]]" @@ -9895,8 +10085,12 @@ msgid "limit to tags" msgstr "batasi ke tag" #: builtin/ls-remote.c -msgid "limit to heads" -msgstr "batasi ke kepala" +msgid "limit to branches" +msgstr "batasi ke cabang" + +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "sinonim usang untuk --branches" #: builtin/ls-remote.c msgid "do not show peeled tags" @@ -10091,18 +10285,6 @@ msgstr "gunakan penggabungan berdasarkan diff3" msgid "use a zealous diff3 based merge" msgstr "gunakan penggabungan berdasarkan diff3 yang bersemangat" -#: builtin/merge-file.c -msgid "for conflicts, use our version" -msgstr "untuk konflik, gunakan versi kami" - -#: builtin/merge-file.c -msgid "for conflicts, use their version" -msgstr "untuk konflik, gunakan versi mereka" - -#: builtin/merge-file.c -msgid "for conflicts, use a union version" -msgstr "untuk konflik, gunakan versi bersatu" - #: builtin/merge-file.c diff.c msgid "<algorithm>" msgstr "<algoritma>" @@ -10398,7 +10580,7 @@ msgstr "Tidak dapat menulis indeks." msgid "Not handling anything other than two heads merge." msgstr "Tak tangani apapun selain penggabungan dua kepala." -#: builtin/merge.c +#: builtin/merge.c builtin/sparse-checkout.c #, c-format msgid "unable to write %s" msgstr "tidak dapat menulis %s" @@ -10698,6 +10880,10 @@ msgid "write multi-pack bitmap" msgstr "tulis bitmap multipak" #: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "tulis MIDX tambahan baru" + +#: builtin/multi-pack-index.c msgid "write multi-pack index containing only given indexes" msgstr "tulis indeks multipak yang hanya berisi indeks yang diberikan" @@ -13177,6 +13363,39 @@ msgstr "tidak ada log referensi yang disebutkan untuk dihapus" 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]" + +#: builtin/refs.c +msgid "git refs verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [---verbose]" + +#: builtin/refs.c +msgid "specify the reference format to convert to" +msgstr "sebutkan format referensi untuk dikonversi" + +#: builtin/refs.c +msgid "perform a non-destructive dry-run" +msgstr "lakukan uji coba non desktruktif" + +#: builtin/refs.c +msgid "missing --ref-format=<format>" +msgstr "--ref-format=<format> hilang" + +#: builtin/refs.c +#, c-format +msgid "repository already uses '%s' format" +msgstr "repositori telah menggunakan format '%s'" + +#: builtin/refs.c +msgid "enable strict checking" +msgstr "aktifkan pemeriksaan lebih ketat" + +#: builtin/refs.c +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' tidak mengambil argumen" + #: builtin/remote.c msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" @@ -13530,10 +13749,6 @@ msgstr "* remote %s" msgid " Fetch URL: %s" msgstr " URL pengambilan: %s" -#: builtin/remote.c -msgid "(no URL)" -msgstr "(tidak ada URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -13544,6 +13759,10 @@ msgid " Push URL: %s" msgstr " URL pendorongan: %s" #: builtin/remote.c +msgid "(no URL)" +msgstr "(tidak ada URL)" + +#: builtin/remote.c #, c-format msgid " HEAD branch: %s" msgstr " Cabang HEAD: %s" @@ -13678,11 +13897,6 @@ msgid "return all URLs" msgstr "kembalikan semua URL" #: builtin/remote.c -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "tidak ada URL yang dikonfigurasi untuk remote '%s'" - -#: builtin/remote.c msgid "manipulate push URLs" msgstr "manipulasi URL pendorongan" @@ -14951,12 +15165,12 @@ msgstr "algoritma hash tidak dikenal" #: builtin/show-ref.c msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pola>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pola>...]" #: builtin/show-ref.c msgid "" @@ -14985,12 +15199,12 @@ msgid "failed to look up reference" msgstr "gagal mencari referensi" #: builtin/show-ref.c -msgid "only show tags (can be combined with heads)" -msgstr "hanya perlihatkan tag (bisa dikombinasikan dengan kepala)" +msgid "only show tags (can be combined with --branches)" +msgstr "hanya perlihatkan tag (bisa dikombinasikan dengan --branches)" #: builtin/show-ref.c -msgid "only show heads (can be combined with tags)" -msgstr "hanya perlihatkan kepala (bisa dikombinasikan dengan tag)" +msgid "only show branches (can be combined with --tags)" +msgstr "hanya perlihatkan cabang (bisa dikombinasikan dengan --tags)" #: builtin/show-ref.c msgid "check for reference existence without resolving" @@ -15057,6 +15271,11 @@ msgid "failed to create directory for sparse-checkout file" msgstr "gagal membuat direktori untuk berkas sparse-checkout" #: builtin/sparse-checkout.c +#, c-format +msgid "unable to fdopen %s" +msgstr "tidak dapat membuka (fdopen) %s" + +#: builtin/sparse-checkout.c msgid "failed to initialize worktree config" msgstr "gagal menginisialisasi konfigurasi pohon kerja" @@ -15626,8 +15845,8 @@ msgstr "tidak dapat hash objek dari '%s'" #: builtin/submodule--helper.c #, c-format -msgid "unexpected mode %o\n" -msgstr "mode tidak diharapkan %o\n" +msgid "unexpected mode %o" +msgstr "mode tidak diharapkan %o" #: builtin/submodule--helper.c msgid "use the commit stored in the index instead of the submodule HEAD" @@ -15765,7 +15984,7 @@ msgstr "Nilai '%s' untuk submodule.alternateErrorStrategy tidak dikenal" msgid "Value '%s' for submodule.alternateLocation is not recognized" msgstr "Nilai '%s' untuk submodule.alternateLocation tidak dikenal" -#: builtin/submodule--helper.c +#: builtin/submodule--helper.c submodule.c #, c-format msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "" @@ -15773,13 +15992,13 @@ msgstr "" #: builtin/submodule--helper.c #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "gagal mengkloning '%s' ke dalam jalur submodul '%s'" +msgid "directory not empty: '%s'" +msgstr "direktori tidak kosong: '%s'" #: builtin/submodule--helper.c #, c-format -msgid "directory not empty: '%s'" -msgstr "direktori tidak kosong: '%s'" +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "gagal mengkloning '%s' ke dalam jalur submodul '%s'" #: builtin/submodule--helper.c #, c-format @@ -16230,9 +16449,11 @@ msgstr "alasan pembaruan" #: builtin/tag.c msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <id kunci>] [-f] [-m <pesan> | -F <berkas>] [-e]\n" +" [(--trailer <token>[(=|:)<nilai>])...]\n" " <nama tag> [<komit> | <objek>]" #: builtin/tag.c @@ -17292,10 +17513,6 @@ msgid "Repository lacks these prerequisite commits:" msgstr "Repositori kekurangan komit prasyarat berikut:" #: bundle.c -msgid "need a repository to verify a bundle" -msgstr "perlu sebuah repositori untuk verifikasi bundel" - -#: bundle.c msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -17825,6 +18042,10 @@ msgid "Manage reflog information" msgstr "Kelola informasi log referensi" #: command-list.h +msgid "Low-level access to refs" +msgstr "Akses tingat bawah ke referensi" + +#: command-list.h msgid "Manage set of tracked repositories" msgstr "Kelola set repositori terlacak" @@ -18226,6 +18447,15 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "bingkah grafik komit data komit yang diperlukan hilang atau rusak" #: commit-graph.c +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"menonaktifkan penyaring Bloom untuk lapisan grafik komit '%s' karena setelan " +"yang tidak cocok" + +#: commit-graph.c msgid "commit-graph has no base graphs chunk" msgstr "grafik komit tidak punya bingkah grafik dasar" @@ -18337,7 +18567,7 @@ msgstr "gagal menulis jumlah id grafik dasar yang benar" msgid "unable to create temporary graph layer" msgstr "tidak dapat membuat lapisan grafik dasar" -#: commit-graph.c +#: commit-graph.c midx-write.c #, c-format msgid "unable to adjust shared permissions for '%s'" msgstr "tidak dapat menyesuaikan perizinan berbagi untuk '%s'" @@ -18384,6 +18614,15 @@ msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "mencoba menulis grafik komit, tapi 'core.commitGraph' dimatikan" #: commit-graph.c +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"mencoba menulis grafik komit, tapi 'commitGraph.changedPathsVersion (%d) " +"tidak didukung" + +#: commit-graph.c msgid "too many commits to write graph" msgstr "terlalu banyak komit untuk menulis grafik" @@ -19703,7 +19942,7 @@ msgstr "" msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "Nilai tidak dikenal untuk variabel konfigurasi 'diff.submodule': '%s'" -#: diff.c transport.c +#: diff.c merge-recursive.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s" @@ -20693,15 +20932,17 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v| --version] [-h | --help] [-C <jalur>] [-c <nama>=<nilai>]\n" " [--exec-path[=<jalur>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects]\n" +" [--no-lazy-fetch] [--no-optional-locks] [--no-advice] [--bare]\n" " [--git-dir=<jalur>] [--work-tree=<jalur>] [--namespace=<nama>]\n" " [--config-env=<nama>=<variabel lingkungan>]\n" " <perintah> [<argumen>]" @@ -21117,14 +21358,14 @@ msgstr "" "ignoredHook false`." #: http-fetch.c +msgid "not a git repository" +msgstr "bukan sebuah repositori git" + +#: http-fetch.c #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "argumen ke --packfile harus sebuah hash valid (dapat '%s')" -#: http-fetch.c -msgid "not a git repository" -msgstr "bukan sebuah repositori git" - #: http.c #, c-format msgid "negative value for http.postBuffer; defaulting to %d" @@ -21139,6 +21380,10 @@ msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "Penyematan kunci publik tidak didukung oleh cURL < 7.39.0" #: http.c +msgid "Unknown value for http.proactiveauth" +msgstr "nilai tidak dikenal untuk http.proactiveauth" + +#: http.c msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE tidak didukung dengan cURL < 7.44.0" @@ -21160,6 +21405,14 @@ msgid "Could not set SSL backend to '%s': already set" msgstr "Tidak dapat menyetel tulang punggung SSL ke '%s': sudah disetel" #: http.c +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "menolak membaca kuki dari http.cookiefile '-'" + +#: http.c +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "mengabaikan http.savecookies karena http.cookiefile kosong" + +#: http.c #, c-format msgid "" "unable to update url base from redirection:\n" @@ -21324,6 +21577,10 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Tidak dapat membuat '%s.lock': %s" +#: log-tree.c +msgid "unable to create temporary object directory" +msgstr "tidak dapat membuat direktori objek sementara" + #: loose.c #, c-format msgid "could not write loose object index %s" @@ -21331,8 +21588,8 @@ msgstr "tidak dapat menulis indeks objek longgar %s" #: loose.c #, c-format -msgid "failed to write loose object index %s\n" -msgstr "gagal menulis indeks objek longgar %s\n" +msgid "failed to write loose object index %s" +msgstr "gagal menulis indeks objek longgar %s" #: ls-refs.c #, c-format @@ -21367,10 +21624,10 @@ msgstr "Gagal menggabungkan submodul %s (tidak ada dasar penggabungan)" msgid "Failed to merge submodule %s (commits not present)" msgstr "Gagal menggabungkan submodul %s (komit tidak ada)" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Gagal menggabungkan submodul %s (repositori rusak)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "kesalahan: gagal menggabungkan submodul %s (repositori rusak)" #: merge-ort.c merge-recursive.c #, c-format @@ -21406,14 +21663,15 @@ msgstr "" "mungkin:\n" "%s" -#: merge-ort.c merge-recursive.c -msgid "failed to execute internal merge" -msgstr "gagal menjalankan penggabungan internal" +#: merge-ort.c +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "kesalahan: gagal menjalankan penggabungan internal untuk %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "unable to add %s to database" -msgstr "tidak dapat menambahkan %s ke basis data" +msgid "error: unable to add %s to database" +msgstr "kesalahan: tidak dapat menambahkan %s ke basis data" #: merge-ort.c merge-recursive.c #, c-format @@ -21520,15 +21778,15 @@ msgstr "" "KONFLIK (penamaan ulang/penghapusan): %s dinamai ulang ke %s di %s, tetapi " "dihapus di %s." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "cannot read object %s" -msgstr "tidak dapat membaca objek %s" +msgid "error: cannot read object %s" +msgstr "kesalahan: tidak dapat membaca objek %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "object %s is not a blob" -msgstr "objek %s bukanlah sebuah blob" +msgid "error: object %s is not a blob" +msgstr "kesalahan: objek %s bukanlah suatu blob" #: merge-ort.c #, c-format @@ -21689,6 +21947,11 @@ msgstr "tidak tahu apa yang dilakukan dengan %06o %s '%s'" #: merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Gagal menggabungkan submodul %s (repositori rusak)" + +#: merge-recursive.c +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Memaju-cepat submodul %s ke komit berikut:" @@ -21735,6 +21998,15 @@ msgid "Failed to merge submodule %s (multiple merges found)" msgstr "Gagal menggabungkan submodul %s (banyak penggabungan ditemukan)" #: merge-recursive.c +msgid "failed to execute internal merge" +msgstr "gagal menjalankan penggabungan internal" + +#: merge-recursive.c +#, c-format +msgid "unable to add %s to database" +msgstr "tidak dapat menambahkan %s ke basis data" + +#: merge-recursive.c #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -21857,6 +22129,16 @@ msgstr "" "%s. Penamaan ulang %s->%s di %s" #: merge-recursive.c +#, c-format +msgid "cannot read object %s" +msgstr "tidak dapat membaca objek %s" + +#: merge-recursive.c +#, c-format +msgid "object %s is not a blob" +msgstr "objek %s bukanlah sebuah blob" + +#: merge-recursive.c msgid "modify" msgstr "ubah" @@ -21962,10 +22244,6 @@ msgid "malformed line: %s" msgstr "baris jelek '%s'." #: midx-write.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok" - -#: midx-write.c msgid "could not load pack" msgstr "tidak dapat memuat pak" @@ -21975,6 +22253,24 @@ msgid "could not open index for %s" msgstr "tidak dapat membuka indeks untuk %s" #: midx-write.c +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "tidak dapat mentautkan '%s' ke '%s'" + +#: midx-write.c midx.c +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "gagal membersihkan indeks multipak pada %s" + +#: midx-write.c +msgid "cannot write incremental MIDX with bitmap" +msgstr "tidak dapat menulis MIDX tambahan dengan bitmap" + +#: midx-write.c +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "Menambahkan berkas pak ke indeks multipak" @@ -22007,14 +22303,30 @@ msgid "refusing to write multi-pack .bitmap without any objects" msgstr "menolak menulis .bitmap multipak tanpa objek apapun" #: midx-write.c +msgid "unable to create temporary MIDX layer" +msgstr "tidak dapat membuat lapisan MIDX sementara" + +#: midx-write.c msgid "could not write multi-pack bitmap" msgstr "tidak dapat menulis bitmap multipak" #: midx-write.c +msgid "unable to open multi-pack-index chain file" +msgstr "tidak dapat membuka berkas rantai indeks multipak" + +#: midx-write.c +msgid "unable to rename new multi-pack-index layer" +msgstr "tidak dapat menamai ulang lapisan indeks multipak baru" + +#: midx-write.c msgid "could not write multi-pack-index" msgstr "gagal menulis indeks multipak" #: midx-write.c +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "tidak dapat mengkadaluarsakan pak dari indeks multipak tambahan" + +#: midx-write.c msgid "Counting referenced objects" msgstr "Menghitung objek tereferensi" @@ -22023,6 +22335,10 @@ msgid "Finding and deleting unreferenced packfiles" msgstr "Mencari dan menghapus berkas pak tak tereferensi" #: midx-write.c +msgid "cannot repack an incremental multi-pack-index" +msgstr "tidak dapat mempak ulang indeks multipak tambahan" + +#: midx-write.c msgid "could not start pack-objects" msgstr "tidak dapat memulai pack-objects" @@ -22099,6 +22415,33 @@ msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "nama pak indeks multipak tidak berurutan: '%s' sebelum '%s'" #: midx.c +msgid "multi-pack-index chain file too small" +msgstr "berkas rantai indeks multipak terlalu kecil" + +#: midx.c +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "jumlah pak pada MIDX dasarterlalu tinggi: %<PRIuMAX>" + +#: midx.c +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "jumlah object pada MIDX dasar terlalu tinggi: %<PRIuMAX>" + +#: midx.c +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "rantai indeks multipak tidak valid: baris '%s' bukan suatu hash" + +#: midx.c +msgid "unable to find all multi-pack index files" +msgstr "tidak dapat menemukan semua berkas indeks multipak" + +#: midx.c +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "posisi objek MIDX tidak valid, MIDX mungkin rusak" + +#: midx.c #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "pack-int-id jelek: %u (total pak %u)" @@ -22121,11 +22464,6 @@ msgid "multi-pack-index large offset out of bounds" msgstr "offset indeks multipak besar di luar jangkauan" #: midx.c -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "gagal membersihkan indeks multipak pada %s" - -#: midx.c msgid "multi-pack-index file exists, but failed to parse" msgstr "berkas indeks multipak ada, tetapi gagal diurai" @@ -22386,6 +22724,16 @@ msgstr "pemetaan %s ke %s hilang" #: object-file.c #, c-format +msgid "unable to open %s" +msgstr "tidak dapat membuka %s" + +#: object-file.c +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "berkas '%s' dan '%s' berbeda konteks" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "tidak dapat menulis berkas %s" @@ -22494,11 +22842,6 @@ msgstr "%s bukan sebuah objek '%s' valid" #: object-file.c #, c-format -msgid "unable to open %s" -msgstr "tidak dapat membuka %s" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "hash tidak cocok untuk %s (diharapkan %s)" @@ -22723,6 +23066,20 @@ msgid "hash mismatch %s" msgstr "hash tidak cocok %s" #: pack-bitmap-write.c +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "entri duplikat ketika menulis indeks bitmap: %s" + +#: pack-bitmap-write.c +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "mencoba menyimpan komit yang tidak dipilih: '%s'" + +#: pack-bitmap-write.c +msgid "too many pseudo-merges" +msgstr "terlalu banyak penggabungan semu" + +#: pack-bitmap-write.c msgid "trying to write commit not in index" msgstr "mencoba menulis komit yang bukan di indeks" @@ -22753,6 +23110,23 @@ msgstr "" "berkas indeks bitmap rusak (terlalu pendek untuk masuk tabel pencarian)" #: pack-bitmap.c +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"berkas indeks bitmap rusak (terlalu pendek untuk masuk kepala tabel " +"penggabungan semu)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"berkas indeks bitmap rusak (terlalu pendek untuk masuk tabel penggabungan " +"semu)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "berkas indeks bitmap rusak (tabel penggabungan semu terlalu pendek)" + +#: pack-bitmap.c #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "entri duplikat di indeks bitmap: '%s'" @@ -22868,6 +23242,11 @@ msgstr "ketidaksesuaian di dalam hasil bitmap" #: pack-bitmap.c #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "indeks penggabungan semu di luar jangkauan (%<PRIu32> >= %<PRIuMAX>)" + +#: pack-bitmap.c +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "tidak dapat menemukan %s di dalam pak '%s' pada offset %<PRIuMAX>" @@ -23325,6 +23704,10 @@ msgid "unable to parse --pretty format" msgstr "tidak dapat menguraikan format --pretty" #: promisor-remote.c +msgid "lazy fetching disabled; some objects may not be available" +msgstr "pengambilan malas dimatikan; beberapa objek mungkin tidak tersedia" + +#: promisor-remote.c msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: tidak dapat menggarpu subproses pengambilan" @@ -23355,6 +23738,83 @@ msgstr "object-info: bilasan diharapkan setelah argumen" msgid "Removing duplicate objects" msgstr "Menghapus objek duplikat" +#: pseudo-merge.c +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "gagal memuat regex penggabungan semu untuk %s: '%s'" + +#: pseudo-merge.c +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s harus non-negatif, menggunakan yang asali" + +#: pseudo-merge.c +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s harus di antara 0 atau 1, menggunakan yang asali" + +#: pseudo-merge.c +#, c-format +msgid "%s must be positive, using default" +msgstr "%s harus positif, menggunakan yang asali" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "grup penggabungan semu '%s' kehilangan pola yang diperlukan" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"grup penggabungan semu '%s' punya ambang batas tidak stabil sebelum yang " +"stabil" + +#: pseudo-merge.c +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"regex penggabungan semu dari konfigurasi punya terlalu banyak grup tangkap " +"(max=%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"pembacaan penggabungan semu yang diperluas di luar batas (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"entri penggabungan semu yang diperluas terlalu pendek (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"tidak dapat menemukan penggabungan semu untuk %s pada offset %<PRIuMAX>" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"pencarian penggabungan semu yang diperluas di luar batas (%<PRIu32> >= " +"%<PRIu32>)" + +#: pseudo-merge.c +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "pembacaan di luar batas: (%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "tidak dapat membaca tabel penggabungan semu untuk komit %s" + #: range-diff.c msgid "could not start `log`" msgstr "tidak dapat memulai `log`" @@ -23868,6 +24328,11 @@ msgstr "format yang diharapkan: %%(ahead-behind:<mirip komit>)" #: ref-filter.c #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "format yang diharapkan: %%(is-base:<mirip komit>)" + +#: ref-filter.c +#, c-format msgid "malformed field name: %.*s" msgstr "nama bidang rusak: %.*s" @@ -24081,12 +24546,21 @@ msgid "log for %s is empty" msgstr "log untuk %s kosong" #: refs.c +msgid "refusing to force and skip creation of reflog" +msgstr "menolak memaksa dan melewatkan pembuatan reflog" + +#: refs.c #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "menolak memperbarui referensi dengan nama jelek '%s'" #: refs.c #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "menolak memperbarui referensi semu '%s'" + +#: refs.c +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "update_ref gagal untuk referensi '%s': %s" @@ -24123,6 +24597,38 @@ msgstr "tidak dapat menghapus referensi %s: %s" msgid "could not delete references: %s" msgstr "tidak dapat menghapus referensi: %s" +#: refs.c +#, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "Selesai uji coba migrasi referensi, hasilnya bisa dilihat di '%s'\n" + +#: refs.c +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "tidak dapat menamai ulang direktori migrasi sementara '%s'" + +#: refs.c +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "referensi termigrasi dapat ditemukan pada '%s'" + +#: refs/files-backend.c refs/reftable-backend.c +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"tidak dapat mengunci referensi '%s': diharapkan referensi simbolik dengan " +"target '%s': tetapi bukan referensi reguler" + +#: refs/files-backend.c +#, c-format +msgid "cannot open directory %s" +msgstr "tidak dapat membuka direktori %s" + +#: refs/files-backend.c +msgid "Checking references consistency" +msgstr "Memeriksa konsistensi referensi" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -24911,12 +25417,16 @@ msgid "create repository within 'src' directory" msgstr "salin repositori di dalam direktori 'src'" #: scalar.c +msgid "specify if tags should be fetched during clone" +msgstr "rincikan jikan tag hendak diambil selama kloning" + +#: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <cabang utama>] [--full-clone]\n" -"\t[--[-no-]src] <url> [<pendaftaran>]" +"\t[--[-no-]src] [--[no-]tags] <url> [<pendaftaran>]" #: scalar.c #, c-format @@ -24940,6 +25450,11 @@ msgstr "tidak dapat menyetel remote di '%s'" #: scalar.c #, c-format +msgid "could not disable tags in '%s'" +msgstr "tidak dapat menonaktifkan tag di '%s'" + +#: scalar.c +#, c-format msgid "could not configure '%s'" msgstr "tidak dapat menyetel '%s'" @@ -25545,6 +26060,55 @@ msgstr "" #: sequencer.c #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' tidak menerima komit penggabungan" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick' tidak mengambil komit penggabungan. Apabila Anda\n" +"ingin memainkan ulang penggabungan, gunakan 'merge -C'\n" +"pada komit." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword' tidak mengambil komit penggabungan. Apabila Anda\n" +"ingin memainkan ulang penggabungan dan menulis ulang pesan\n" +"komit, gunakan 'merge -c' pada komit" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +#: sequencer.c +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'edit' tidak mengambil komit penggabungan. Apabila Anda\n" +"ingin memainkan ulang komit, gunakan 'merge -C' pada komit,\n" +"lalu 'break' untuk memberikan Anda kembali kendali agar\n" +"Anda dapat menjalankan 'git commit --amend && git rebase --continue'." + +#: sequencer.c +msgid "cannot squash merge commit into another commit" +msgstr "tidak dapat melumatkan komit penggabungan ke dalam komit lainnya" + +#: sequencer.c +#, c-format msgid "invalid command '%.*s'" msgstr "perintah tidak valid '%.*s'" @@ -25695,9 +26259,8 @@ msgid "cannot read HEAD" msgstr "tidak dapat membaca HEAD" #: sequencer.c -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "tidak dapat menyalin '%s' ke '%s'" +msgid "could not write commit message file" +msgstr "tidak dapat menulis berkas pesan komit" #: sequencer.c #, c-format @@ -26180,6 +26743,24 @@ msgid "failed to stat '%*s%s%s'" msgstr "gagal men-stat '%*s%s%s'" #: setup.c +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' bukan mutlak" + +#: setup.c +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"perizinan meragukan terdeteksi di dalam repositori pada '%s'\n" +"%sUntuk menambahkan pengecualian untuk direktori ini, panggil:\n" +"\n" +"\tgit config --global --add safe.directory %s" + +#: setup.c msgid "Unable to read current working directory" msgstr "tidak dapat membaca direktori kerja saat ini" @@ -26205,19 +26786,6 @@ msgstr "" #: setup.c #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"perizinan meragukan terdeteksi di dalam repositori pada '%s'\n" -"%sUntuk menambahkan pengecualian untuk direktori ini, panggil:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#: setup.c -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "" "tidak dapat menggunakan repositori bare '%s' (safe.bareRepository yaitu '%s')" @@ -26591,6 +27159,17 @@ msgstr "direktori submodul git '%s' di dalam direktori git '%.*s'" #: submodule.c #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"'%.*s' diharapkan di jalur submodul '%s' yang tidak menjadi tautan simbolik" + +#: submodule.c +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "jalur submodul '%s' diharapkan yang tidak menjadi tautan simbolik" + +#: submodule.c +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -26637,11 +27216,6 @@ msgid "no remote configured to get bundle URIs from" msgstr "tidak ada remote yang dikonfigurasi untuk mendapatkan URI bundel" #: t/helper/test-bundle-uri.c -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "remote '%s' tidak punya URL terkonfigurasi" - -#: t/helper/test-bundle-uri.c msgid "could not get the bundle-uri list" msgstr "tidak dapat mendapatkan daftar bundle-uri" @@ -26748,6 +27322,30 @@ msgstr "token" msgid "command token to send to the server" msgstr "token perintah untuk dikirim ke peladen" +#: t/unit-tests/unit-test.c +msgid "unit-test [<options>]" +msgstr "unit-test [<opsi>]" + +#: t/unit-tests/unit-test.c +msgid "immediately exit upon the first failed test" +msgstr "langsung keluar pada saat kegagalan tes pertama" + +#: t/unit-tests/unit-test.c +msgid "suite[::test]" +msgstr "suite[::test]" + +#: t/unit-tests/unit-test.c +msgid "run only test suite or individual test <suite[::test]>" +msgstr "hanya jalankan rangkaian tes atau tes individu <suite[::test]>" + +#: t/unit-tests/unit-test.c +msgid "suite" +msgstr "rangkaian" + +#: t/unit-tests/unit-test.c +msgid "exclude test suite <suite>" +msgstr "kecualikan rangkaian tes <rangkaian>" + #: trailer.c #, c-format msgid "running trailer command '%s' failed" @@ -28197,6 +28795,10 @@ msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases tidak kompatibel dengan opsi yang lain\n" #: git-send-email.perl +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases dan --translate-aliases saling eksklusif\n" + +#: git-send-email.perl msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -28440,29 +29042,29 @@ msgstr "Gagal mengirim %s\n" #: git-send-email.perl #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Terkirim-kering %s\n" +msgid "Dry-Sent %s" +msgstr "Uji-coba-Terkirim %s" #: git-send-email.perl #, perl-format -msgid "Sent %s\n" -msgstr "Terkirim %s\n" +msgid "Sent %s" +msgstr "Terkirim %s" #: git-send-email.perl -msgid "Dry-OK. Log says:\n" -msgstr "OK-kering. Log berkata:\n" +msgid "Dry-OK. Log says:" +msgstr "Uji-coba-OK. Log berkata:" #: git-send-email.perl -msgid "OK. Log says:\n" -msgstr "OK. Log berkata:\n" +msgid "OK. Log says:" +msgstr "OK. Log berkata:" #: git-send-email.perl msgid "Result: " msgstr "Hasil: " #: git-send-email.perl -msgid "Result: OK\n" -msgstr "Hasil: OK\n" +msgid "Result: OK" +msgstr "Hasil: OK" #: git-send-email.perl #, perl-format @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: git 2.45.0\n" +"Project-Id-Version: git 2.47.0\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-27 15:19+0100\n" -"PO-Revision-Date: 2024-04-27 15:20+0100\n" +"POT-Creation-Date: 2024-09-19 02:06+0000\n" +"PO-Revision-Date: 2024-09-28 15:45+0100\n" "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n" "Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -542,7 +542,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - lämna stycket obestämt, se nästa obestämda stycke\n" @@ -553,9 +553,13 @@ msgstr "" "/ - sök efter stycke som motsvarar angivet reguljärt uttryck\n" "s - dela aktuellt stycke i mindre styckens\n" "e - redigera aktuellt stycke manuellt\n" -"p - visa aktuellt stycke\n" +"p - visa aktuellt stycke, â€P†för att använda bläddrare\n" "? - visa hjälp\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Förväntade endast en bokstav, fick â€%sâ€" + msgid "No previous hunk" msgstr "Inget föregÃ¥ende stycke" @@ -604,9 +608,19 @@ msgstr "Dela i %d stycken." msgid "Sorry, cannot edit this hunk" msgstr "Beklagar, kan inte redigera stycket" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Okänt kommando â€%s†(använd â€?†för hjälp)" + msgid "'git apply' failed" msgstr "â€git apply†misslyckades" +msgid "No changes." +msgstr "Inga ändringar." + +msgid "Only binary files changed." +msgstr "Endast binära filer ändrade." + #, c-format msgid "" "\n" @@ -650,7 +664,7 @@ msgstr "" "som lämpligt för att ange lösning och checka in." msgid "Exiting because of an unresolved conflict." -msgstr "Avslutar pÃ¥ grund av olöst konflikgt." +msgstr "Avslutar pÃ¥ grund av olöst konflikt." msgid "You have not concluded your merge (MERGE_HEAD exists)." msgstr "Du har inte avslutat sammanslagningen (MERGE_HEAD finns)." @@ -1215,6 +1229,15 @@ msgstr "" "försök en trevägssammanslagning, fall tillbaka pÃ¥ normal patch om det " "misslyckas" +msgid "for conflicts, use our version" +msgstr "för konflikter, använd vÃ¥r version" + +msgid "for conflicts, use their version" +msgstr "för konflikter, använd deras version" + +msgid "for conflicts, use a union version" +msgstr "för konflikter, använd en förenad version" + msgid "build a temporary index based on embedded index information" msgstr "bygg ett temporärt index baserat pÃ¥ inbyggd indexinformation" @@ -1260,6 +1283,9 @@ msgstr "lägg till <rot> i alla filnamn" msgid "don't return error for empty patches" msgstr "ge inte nÃ¥gon felkod för tomma patchar" +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs, och --union kräver --3way" + #, c-format msgid "cannot stream blob %s" msgstr "kan inte strömma blob:en %s" @@ -1461,6 +1487,9 @@ msgstr "ignorerar allt för stor gitattributes-fil â€%sâ€" msgid "ignoring overly large gitattributes blob '%s'" msgstr "ignorerar allt för stor gitattributes-objekt â€%sâ€" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "kan inte använda --attr-source eller GIT_ATTR_SOURCE utan arkiv" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "felaktig --attr-source eller GIT_ATTR_SOURCE" @@ -1778,13 +1807,6 @@ msgstr "kan inte utföra chmod %cx â€%sâ€" msgid "Unstaged changes after refreshing the index:" msgstr "Oköade ändringar efter att ha uppdaterat indexet:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"inställningen add.interactive.useBuiltin har tagits bort!\n" -"Se dess post i â€git help config†för detaljer." - msgid "could not read the index" msgstr "kunde inte läsa indexet" @@ -2219,6 +2241,9 @@ msgstr "avbryt patchningen men behÃ¥ll HEAD där det är" msgid "show the patch being applied" msgstr "visa patchen som tillämpas" +msgid "try to apply current patch again" +msgstr "försök applicera aktuell patch pÃ¥ nytt" + msgid "record the empty patch as an empty commit" msgstr "lagra den tomma patchen som en tom incheckning" @@ -2274,9 +2299,6 @@ msgstr "git apply [<flaggor>] [<patch>...]" msgid "could not redirect output" msgstr "kunde inte omdirigera utdata" -msgid "git archive: Remote with no URL" -msgstr "git archive: Fjärr utan URL" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: förväntade ACK/NAK, fick flush-paket" @@ -2430,9 +2452,6 @@ msgstr "" "ogiltigt argument %s för â€git bisect termsâ€.\n" "Flaggor som stöds är: --term-good|--term-old och --term-bad|--term-new." -msgid "revision walk setup failed\n" -msgstr "misslyckades starta revisionstraversering\n" - #, c-format msgid "could not open '%s' for appending" msgstr "kunde inte öppna â€%s†för tillägg" @@ -3169,6 +3188,9 @@ msgstr "Behöver ett arkiv för att skapa en bunt." msgid "do not show bundle details" msgstr "visa inte buntdetaljer" +msgid "need a repository to verify a bundle" +msgstr "behöver ett arkiv för att bekräfta en bunt." + #, c-format msgid "%s is okay\n" msgstr "%s är okej\n" @@ -3401,9 +3423,14 @@ msgstr "git check-mailmap [<flaggor>] <kontakt>..." msgid "also read contacts from stdin" msgstr "läs även kontakter frÃ¥n standard in" -#, c-format -msgid "unable to parse contact: %s" -msgstr "kan inte tolka kontakt: %s" +msgid "read additional mailmap entries from file" +msgstr "läs ytterligare mailmap-poster frÃ¥n fil" + +msgid "blob" +msgstr "blob" + +msgid "read additional mailmap entries from blob" +msgstr "läs ytterligare mailmap-poster frÃ¥n blob" msgid "no contacts specified" msgstr "inga kontakter angavs" @@ -3752,6 +3779,10 @@ msgid "'%s' cannot be used with switching branches" msgstr "â€%s†kan inte användas vid byte av gren" #, c-format +msgid "'%s' needs the paths to check out" +msgstr "â€%s†behöver sökvägar att checka ut" + +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "â€%s†kan inte användas med â€%sâ€" @@ -4174,6 +4205,14 @@ 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â€" @@ -4500,7 +4539,7 @@ msgstr "git commit-tree: misslyckades läsa" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4510,7 +4549,7 @@ msgid "" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<läge>] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <incheckning> | --fixup [(amend|" -"reword):]<incheckning>)]\n" +"reword):]<incheckning>]\n" " [-F <fil> | -m <medd>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--" "author=<författare>]\n" @@ -4996,15 +5035,57 @@ msgstr "" "att kvoten inte har överskridits, och kör sedan\n" "â€git restore --staged :/†för att Ã¥terställa." -msgid "git config [<options>]" -msgstr "git config [<flaggor>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<filflagga>] [<visningsflagga>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "okänt argument för --type, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<filflagga>] [<visningsflagga>] [--includes] [--all] [--" +"regexp] [--value=<värde>] [--fixed-value] [--default=<förval>] <namn>" -msgid "only one type at a time" -msgstr "endast en typ Ã¥t gÃ¥ngen" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<filflagga>] [--type=<typ>] [--all] [--value=<värde>] [--" +"fixed-value] <namn> <värde>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<filflagga>] [--all] [--value=<värde>] [--fixed-value] " +"<namn> <värde>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<filflagga>] <gammalt-namn> <nytt-namn>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<filflagga>] <namn>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<filflagga>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<filflagga>] --get-colorbool <namn> [<stdout-är-tty>]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<filflagga>] [<visningsflagga>] [--includes] [--all] [--" +"regexp=<reguttr>] [--value=<värde>] [--fixed-value] [--default=<förval>] " +"<namn>" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<filflagga>] [--type=<typ>] [--comment=<meddelande>] [--all] " +"[--value=<värde>] [--fixed-value] <namn> <värde>" msgid "Config file location" msgstr "Konfigurationsfilens plats" @@ -5030,54 +5111,6 @@ msgstr "blob-id" msgid "read config from given blob object" msgstr "läs konfiguration frÃ¥n givet blob-objekt" -msgid "Action" -msgstr "Ã…tgärd" - -msgid "get value: name [value-pattern]" -msgstr "hämta värde: namn [värde-mönster]" - -msgid "get all values: key [value-pattern]" -msgstr "hämta alla värden: nyckel [värde-mönster]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "hämta värden för reguttr: namn-reguttr [värde-mönster]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "hämta värde specifikt URL:en: sektion[.var] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "ersätt alla motsvarande variabler: namn värde [värde-mönster]" - -msgid "add a new variable: name value" -msgstr "lägg till en ny variabel: namn värde" - -msgid "remove a variable: name [value-pattern]" -msgstr "ta bort en variabel: namn [värde-mönster]" - -msgid "remove all matches: name [value-pattern]" -msgstr "ta bort alla träffar: namn [värde-mönster]" - -msgid "rename section: old-name new-name" -msgstr "byt namn pÃ¥ sektion: gammalt-namn nytt-namn" - -msgid "remove a section: name" -msgstr "ta bort en sektion: namn" - -msgid "list all" -msgstr "visa alla" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "använd stränglikhet vid när värden jämförs med â€värde-mönsterâ€" - -msgid "open an editor" -msgstr "öppna textredigeringsprogram" - -msgid "find the color configured: slot [default]" -msgstr "hitta den inställda färgen: slot [default]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "hitta färginställningen: slot [stdout-is-tty]" - msgid "Type" msgstr "Typ" @@ -5105,8 +5138,8 @@ msgstr "värdet är en sökväg (fil- eller katalognamn)" msgid "value is an expiry date" msgstr "värdet är ett utgÃ¥ngsdatum" -msgid "Other" -msgstr "Andra" +msgid "Display options" +msgstr "Visningsflaggor" msgid "terminate values with NUL byte" msgstr "terminera värden med NUL-byte" @@ -5114,9 +5147,6 @@ msgstr "terminera värden med NUL-byte" msgid "show variable names only" msgstr "visa endast variabelnamn" -msgid "respect include directives on lookup" -msgstr "respektera inkluderingsdirektiv vid uppslag" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "visa konfigurationskälla (fil, standard in, blob, kommandorad)" @@ -5125,14 +5155,15 @@ msgstr "" "visa omfÃ¥ng för konfiguration (arbetskatalog, lokalt, globalt, system, " "kommando)" -msgid "value" -msgstr "värde" +msgid "show config keys in addition to their values" +msgstr "visa konfigurationsnycklar tillsammans med deras värden" -msgid "with --get, use default value when missing entry" -msgstr "med --get, använd standardvärde vid saknad post" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "okänt argument för --type, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "människoläsbar kommentarssträng (# läggs in först efter behov)" +msgid "only one type at a time" +msgstr "endast en typ Ã¥t gÃ¥ngen" #, c-format msgid "wrong number of arguments, should be %d" @@ -5208,46 +5239,72 @@ msgstr "" "konfigurationsutöknignen worktreeConfig har aktiverats. Läsa stycket\n" "â€KONFIGURATIONSFIL†i â€git help worktree†för detaljer" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color och variabeltyp stämmer inte överens" +msgid "Other" +msgstr "Andra" -msgid "only one action at a time" -msgstr "endast en Ã¥tgärd Ã¥t gÃ¥ngen" +msgid "respect include directives on lookup" +msgstr "respektera inkluderingsdirektiv vid uppslag" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only gäller bara för --list eller --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "kan inte läsa konfigurationsfilen â€%sâ€" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"--show-origin gäller bara för --get, --get-all, --get-regexp och --list" +msgid "error processing config file(s)" +msgstr "fel vid hantering av konfigurationsfil(er)" -msgid "--default is only applicable to --get" -msgstr "--default gäller bara för --get" +msgid "Filter options" +msgstr "Filterflaggor" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment gäller bara för â€getâ€/â€setâ€/â€replaceâ€-operationerna" +msgid "return all values for multi-valued config options" +msgstr "returnera alla värden för konfigurationsflaggor med flera värden" + +msgid "interpret the name as a regular expression" +msgstr "tolka namnet som reguljärt uttryck" + +msgid "show config with values matching the pattern" +msgstr "via konfiguration med värden som motsvarar mönster" + +msgid "use string equality when comparing values to value pattern" +msgstr "använd stränglikhet vid när värden jämförs med värde-mönster" + +msgid "URL" +msgstr "URL" + +msgid "show config matching the given URL" +msgstr "visa konfiguration som motsvarar given URL" + +msgid "value" +msgstr "värde" + +msgid "use default value when missing entry" +msgstr "använd standardvärde vid saknad post" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value gäller endast med â€värde-mönsterâ€" -#, c-format -msgid "unable to read config file '%s'" -msgstr "kan inte läsa konfigurationsfilen â€%sâ€" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= kan inte användas med --all eller --url=" -msgid "error processing config file(s)" -msgstr "fel vid hantering av konfigurationsfil(er)" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= kan inte användas med --all, --regexp eller --value" -msgid "editing stdin is not supported" -msgstr "redigering av standard in stöds ej" +msgid "Filter" +msgstr "Filter" -msgid "editing blobs is not supported" -msgstr "redigering av blobbar stöds ej" +msgid "replace multi-valued config option with new value" +msgstr "ersätt konfigurationsflagga med flera värden med nytt värde" -#, c-format -msgid "cannot create configuration file %s" -msgstr "kan inte skapa konfigurationsfilen â€%sâ€" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "människoläsbar kommentarssträng (# läggs in först efter behov)" + +msgid "add a new line without altering any existing values" +msgstr "lägg till ny rad utan att ändra befintliga värden" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value gäller endast med --value=<mönster>" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append kan inte användas med --value=<mönster>" #, c-format msgid "" @@ -5261,6 +5318,85 @@ msgstr "" msgid "no such section: %s" msgstr "ingen sÃ¥dan sektion: %s" +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" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "kan inte skapa konfigurationsfilen â€%sâ€" + +msgid "Action" +msgstr "Ã…tgärd" + +msgid "get value: name [<value-pattern>]" +msgstr "hämta värde: namn <värde-mönster>" + +msgid "get all values: key [<value-pattern>]" +msgstr "hämta alla värden: nyckel <värde-mönster>" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "hämta värden för reguttr: namn-reguttr <värde-mönster>" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "hämta värde specifikt URL:en: sektion[.var] URL" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "ersätt alla motsvarande variabler: namn värde <värde-mönster>" + +msgid "add a new variable: name value" +msgstr "lägg till en ny variabel: namn värde" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "ta bort en variabel: namn <värde-mönster>" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "ta bort alla träffar: namn <värde-mönster>" + +msgid "rename section: old-name new-name" +msgstr "byt namn pÃ¥ sektion: gammalt-namn nytt-namn" + +msgid "remove a section: name" +msgstr "ta bort en sektion: namn" + +msgid "list all" +msgstr "visa alla" + +msgid "open an editor" +msgstr "öppna textredigeringsprogram" + +msgid "find the color configured: slot [<default>]" +msgstr "hitta den inställda färgen: lucka <förval>" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "hitta färginställningen: lucka <stdout-är-tty>" + +msgid "with --get, use default value when missing entry" +msgstr "med --get, använd standardvärde vid saknad post" + +msgid "--get-color and variable type are incoherent" +msgstr "--get-color och variabeltyp stämmer inte överens" + +msgid "no action specified" +msgstr "ingen handling angavs" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only gäller bara för --list eller --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin gäller bara för --get, --get-all, --get-regexp och --list" + +msgid "--default is only applicable to --get" +msgstr "--default gäller bara för --get" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment gäller bara för â€getâ€/â€setâ€/â€replaceâ€-operationerna" + msgid "print sizes in human readable format" msgstr "skriv storlekar i människoläsbart format" @@ -5742,8 +5878,8 @@ msgstr "" "false†för att undvika testet\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s sände inte alla nödvändiga objekt\n" +msgid "%s did not send all necessary objects" +msgstr "%s sände inte alla nödvändiga objekt" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -5780,8 +5916,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "flaggan â€%s†med värdet â€%s†är inte giltigt för %s" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "flaggan â€%s†ignoreras för %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "flaggan â€%s†ignoreras för %s" #, c-format msgid "%s is not a valid object" @@ -6079,6 +6215,9 @@ msgstr "konfig" msgid "config key storing a list of repository paths" msgstr "konfigurationsnyckel som innehÃ¥ller en lista över arkivsökvägar" +msgid "keep going even if command fails in a repository" +msgstr "fortsätt även om kommandot misslyckas i ett arkiv" + msgid "missing --config=<config>" msgstr "saknar --config=<konfig>" @@ -6454,6 +6593,9 @@ msgstr "var mer grundlig (ökar körtiden)" msgid "enable auto-gc mode" msgstr "aktivera auto-gc-läge" +msgid "perform garbage collection in the background" +msgstr "utför skräpsamling i bakgrunden" + msgid "force running gc even if there may be another gc running" msgstr "tvinga gc-körning även om en annan gc kanske körs" @@ -6550,6 +6692,9 @@ msgstr "uppgiften â€%s†kan inte väljas flera gÃ¥nger" msgid "run tasks based on the state of the repository" msgstr "kör uppgifter baserad pÃ¥ arkivets tillstÃ¥nd" +msgid "perform maintenance in the background" +msgstr "utför underhÃ¥ll i bakgrunden" + msgid "frequency" msgstr "frekvens" @@ -7407,9 +7552,6 @@ msgstr "-L<intervall>:<fil> kan inte användas med sökvägsspecifikation" msgid "Final output: %d %s\n" msgstr "Slututdata: %d %s\n" -msgid "unable to create temporary object directory" -msgstr "kan inte skapa temporär objektkatalog" - #, c-format msgid "git show %s: bad file" msgstr "git show %s: felaktig fil" @@ -7531,8 +7673,11 @@ msgstr "markera serien som N:te försök" msgid "max length of output filename" msgstr "maximal längd för utdatafilnamn" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "använd [RFC PATCH] istället för [PATCH]" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "lägg till <rfc> (förval â€RFCâ€) före â€PATCHâ€" msgid "cover-from-description-mode" msgstr "cover-from-description-läge" @@ -7793,11 +7938,11 @@ msgstr "" "deduplicate, --eol" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<nyckel>]\n" " [--symref] [<arkiv> [<mönster>...]]" @@ -7813,8 +7958,11 @@ msgstr "sökväg till git-upload-pack pÃ¥ fjärren" msgid "limit to tags" msgstr "begränsa till taggar" -msgid "limit to heads" -msgstr "begränsa till huvuden" +msgid "limit to branches" +msgstr "begränsa till grenar" + +msgid "deprecated synonym for --branches" +msgstr "förÃ¥ldrad synonym till --branches" msgid "do not show peeled tags" msgstr "visa inte avskalade taggar" @@ -7960,15 +8108,6 @@ msgstr "använd diff3-baserad sammanslagning" msgid "use a zealous diff3 based merge" msgstr "använd nitisk diff3-baserad sammanslagning" -msgid "for conflicts, use our version" -msgstr "för konflikter, använd vÃ¥r version" - -msgid "for conflicts, use their version" -msgstr "för konflikter, använd deras version" - -msgid "for conflicts, use a union version" -msgstr "för konflikter, använd en förenad version" - msgid "<algorithm>" msgstr "<algoritm>" @@ -8433,6 +8572,9 @@ msgstr "paket att Ã¥teranvända vid beräkning av multipaketsbitkarta" msgid "write multi-pack bitmap" msgstr "skriv flerpaketsbitkarta" +msgid "write a new incremental MIDX" +msgstr "skriv en ny inkrementell MIDX" + msgid "write multi-pack index containing only given indexes" msgstr "skriv flerpaketsindex som endast innehÃ¥ller angivna index" @@ -10423,6 +10565,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +msgstr "ange referensformatet att konvertera till" + +msgid "perform a non-destructive dry-run" +msgstr "utför ett icke-destruktiv testkörning" + +msgid "missing --ref-format=<format>" +msgstr "saknad --ref-format=<format>" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "arkivet använder redan â€%sâ€-format" + +msgid "enable strict checking" +msgstr "aktivera strikt kontroll" + +msgid "'git refs verify' takes no arguments" +msgstr "â€git refs verify†tar inget argument" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -10703,9 +10870,6 @@ msgstr "* fjärr %s" msgid " Fetch URL: %s" msgstr " Hämt-URL: %s" -msgid "(no URL)" -msgstr "(ingen URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -10714,6 +10878,9 @@ msgstr "(ingen URL)" msgid " Push URL: %s" msgstr " Sänd-URL: %s" +msgid "(no URL)" +msgstr "(ingen URL)" + #, c-format msgid " HEAD branch: %s" msgstr " HEAD-gren: %s" @@ -10819,10 +10986,6 @@ msgstr "frÃ¥ga sänd-URL:er istället för hämta-URL:er" msgid "return all URLs" msgstr "returnera alla URL:er" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "ingen URL:er angivna för fjärren â€%sâ€" - msgid "manipulate push URLs" msgstr "manipulera URL:ar för sändning" @@ -11818,12 +11981,12 @@ msgstr "okänd hashningsalgoritm" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<mönster>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<mönster>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -11846,11 +12009,11 @@ msgstr "referensen existerar inte" msgid "failed to look up reference" msgstr "misslyckades slÃ¥ upp referensen" -msgid "only show tags (can be combined with heads)" -msgstr "visa endast taggar (kan kombineras med huvuden)" +msgid "only show tags (can be combined with --branches)" +msgstr "visa endast taggar (kan kombineras med --branches)" -msgid "only show heads (can be combined with tags)" -msgstr "visa endast huvuden (kan kombineras med taggar)" +msgid "only show branches (can be combined with --tags)" +msgstr "visa endast grenar (kan kombineras med --tags)" msgid "check for reference existence without resolving" msgstr "kontrollerar att referensen existerar utan att slÃ¥ upp dem" @@ -11902,6 +12065,10 @@ msgstr "misslyckades ta bort katalogen â€%sâ€" msgid "failed to create directory for sparse-checkout file" msgstr "misslyckades skapa katalog för â€sparse-checkoutâ€-filen" +#, c-format +msgid "unable to fdopen %s" +msgstr "kan inte utföra fdopen %s" + msgid "failed to initialize worktree config" msgstr "misslyckades initiera arbetskataloginställning" @@ -12353,8 +12520,8 @@ msgid "couldn't hash object from '%s'" msgstr "kunde inte hasha objekt frÃ¥n â€%sâ€" #, c-format -msgid "unexpected mode %o\n" -msgstr "okänt läge %o\n" +msgid "unexpected mode %o" +msgstr "okänt läge %o" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "använd incechkning lagrad i indexet istället för undermodulens HEAD" @@ -12471,14 +12638,14 @@ msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "vägrar skapa/använda â€%s†i en annan undermoduls gitkatalog" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "misslyckades klona â€%s†till undermodulsökvägen â€%sâ€" - -#, c-format msgid "directory not empty: '%s'" msgstr "katalogen inte tom: â€%sâ€" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +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â€" @@ -12835,9 +13002,11 @@ msgstr "skäl till uppdateringen" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <nyckel-id>] [-f] [-m <medd> | -F <fil>] [-e]\n" +" [(--trailer <symbol>[(=|:)<värde>])...]\n" " <taggnamn> [<incheckning> | <objekt>]" msgid "git tag -d <tagname>..." @@ -13682,9 +13851,6 @@ msgstr "okänt huvud: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Arkivet saknar dessa nödvändiga incheckningar:" -msgid "need a repository to verify a bundle" -msgstr "behöver ett arkiv för att bekräfta en bunt." - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14082,6 +14248,9 @@ msgstr "Ta emot det som sänds till arkivet" msgid "Manage reflog information" msgstr "Hantera referenslogg-information" +msgid "Low-level access to refs" +msgstr "LÃ¥gnivååtkomst till referenser" + msgid "Manage set of tracked repositories" msgstr "Hantera uppsättningen spÃ¥rade arkiv" @@ -14387,6 +14556,14 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "" "incheckningsgrafens nödvändiga incheckningsdatastycke saknas eller är trasigt" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"inaktivera Bloom-filter för incheckningsgraflager â€%s†pÃ¥ grund av " +"inkompatibla inställningar" + msgid "commit-graph has no base graphs chunk" msgstr "incheckningsgrafen har inga bas-graf-stycken" @@ -14510,6 +14687,14 @@ msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "" "försöker skriva en incheckningsgraf, men â€core.commitGraph†är inaktiverad" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph." +"changedPathsVersion' (%d) is not supported" +msgstr "" +"försöker skriva en incheckningsgraf, men â€commitGraph." +"changedPathsVersion†(%d) stöds inte" + msgid "too many commits to write graph" msgstr "för mÃ¥nga incheckningar för att skriva graf" @@ -16348,18 +16533,23 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h |--help] [-C <sökväg>] [-c <namn>=<värde>]\n" " [--exec-path[=<sökväg>]] [--html-path] [--man-path] [--info-" "path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<sökväg>] [--work-tree=<sökväg>] [--namespace=<namn>]\n" -" [--config-env=<namn>=<miljövar>] <kommando> [<flaggor>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-" +"dir=<sökväg>]\n" +" [--work-tree=<sökväg>] [--namespace=<namn>] [--config-" +"env=<namn>=<miljövar>]\n" +" <kommando> [<flaggor>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -16695,14 +16885,14 @@ msgstr "" "Kroken â€%s†ignorerades eftersom den inte är markerad som körbar.\n" "Du kan inaktivera varningen med â€git config advice.ignoredHook falseâ€." +msgid "not a git repository" +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')" -msgid "not a git repository" -msgstr "inte ett git-arkiv" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "http.postBuffer har negativt värde; använder förvalet %d" @@ -16713,6 +16903,9 @@ msgstr "Delegerad styrning stöds inte av cURL < 7.22.0" msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "FastnÃ¥lning av öppen nyckel stöds inte av cURL < 7.39.0" +msgid "Unknown value for http.proactiveauth" +msgstr "Okänt värde för http.proactiveauth" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE stöds inte av cURL < 7.44.0" @@ -16728,6 +16921,12 @@ msgstr "Kan inte sätta SSL-bakända till â€%sâ€: cURL byggdes utan SSL-bakän msgid "Could not set SSL backend to '%s': already set" msgstr "Kunde inte sätta SSL-bakända till â€%sâ€: redan valt" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "vägrar läsa kakor frÃ¥n filen â€-†angiven i http.cookiefile" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "ignorerar http.savecookies för tom http.cookiefile" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -16867,13 +17066,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Kunde inte skapa â€%s.lockâ€: %s" +msgid "unable to create temporary object directory" +msgstr "kan inte skapa temporär objektkatalog" + #, c-format msgid "could not write loose object index %s" msgstr "kunde inte skriva löst objektindex %s" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "misslyckades skriva löst objektindex %s\n" +msgid "failed to write loose object index %s" +msgstr "misslyckades skriva löst objektindex %s" #, c-format msgid "unexpected line: '%s'" @@ -16902,8 +17104,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Misslyckades slÃ¥ ihop undermodulen %s (incheckningar saknas)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Misslyckades slÃ¥ ihop undermodulen %s (arkivet är trasigt)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "fel: misslyckades slÃ¥ ihop undermodulen %s (arkivet är trasigt)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -16933,12 +17135,13 @@ msgstr "" "finns:\n" "%s" -msgid "failed to execute internal merge" -msgstr "misslyckades exekvera intern sammanslagning" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "fel: misslyckades exekvera intern sammanslagning för %s" #, c-format -msgid "unable to add %s to database" -msgstr "kan inte lägga till %s till databasen" +msgid "error: unable to add %s to database" +msgstr "fel: kan inte lägga till %s till databasen" #, c-format msgid "Auto-merging %s" @@ -17031,12 +17234,12 @@ msgstr "" "KONFLIKT (namnbyte/radera): %s namnbytt till %s i %s, men borttagen i %s." #, c-format -msgid "cannot read object %s" -msgstr "kan inte läsa objektet %s" +msgid "error: cannot read object %s" +msgstr "fel: kan inte läsa objektet %s" #, c-format -msgid "object %s is not a blob" -msgstr "objektet %s är inte en blob" +msgid "error: object %s is not a blob" +msgstr "fel: objektet %s är inte en blob" #, c-format msgid "" @@ -17176,6 +17379,10 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "vet inte hur %06o %s â€%s†ska hanteras" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Misslyckades slÃ¥ ihop undermodulen %s (arkivet är trasigt)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Snabbspolar undermodulen %s till följande incheckning:" @@ -17217,6 +17424,13 @@ msgid "Failed to merge submodule %s (multiple merges found)" msgstr "" "Misslyckades slÃ¥ ihop undermodulen %s (flera sammanslagningar hittades)" +msgid "failed to execute internal merge" +msgstr "misslyckades exekvera intern sammanslagning" + +#, c-format +msgid "unable to add %s to database" +msgstr "kan inte lägga till %s till databasen" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "Fel: Vägrar förlora ospÃ¥rad fil vid %s; skriver till %s istället." @@ -17312,6 +17526,14 @@ msgstr "" "KONFLIKT (namnbyte/namnbyte): Namnbytt katalog %s→%s i %s. Namnbytt katalog " "%s→%s i %s" +#, c-format +msgid "cannot read object %s" +msgstr "kan inte läsa objektet %s" + +#, c-format +msgid "object %s is not a blob" +msgstr "objektet %s är inte en blob" + msgid "modify" msgstr "ändra" @@ -17395,9 +17617,6 @@ msgstr "kunde inte tolka rad: %s" msgid "malformed line: %s" msgstr "felaktig rad: %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "ignorerar befintlig multi-pack-index; felaktig kontrollsumma" - msgid "could not load pack" msgstr "kunde inte läsa paket{" @@ -17405,6 +17624,20 @@ msgstr "kunde inte läsa paket{" msgid "could not open index for %s" msgstr "kunde inte öppna indexet för %s" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "kan inte länka â€%s†till â€%sâ€" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "misslyckades städa multi-pack-index pÃ¥ %s" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "kan inte skriva inkrementell MIDX med bitkarta" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "ignorerar befintlig multi-pack-index; felaktig kontrollsumma" + msgid "Adding packfiles to multi-pack-index" msgstr "Lägger till paketfiler till multi-pack-index" @@ -17430,18 +17663,33 @@ msgstr "inga paketfiler att indexera." msgid "refusing to write multi-pack .bitmap without any objects" msgstr "kunde inte skriva fler-paketsbitkarta utan nÃ¥gra objekt" +msgid "unable to create temporary MIDX layer" +msgstr "kan inte skapa temporärt MIDX-lager" + msgid "could not write multi-pack bitmap" msgstr "kunde inte skriva fler-paketsbitkarta" +msgid "unable to open multi-pack-index chain file" +msgstr "kan inte öppna kedjefil för multi-pack-index" + +msgid "unable to rename new multi-pack-index layer" +msgstr "kan inte byta namn pÃ¥ nytt multi-pack-index-lager" + msgid "could not write multi-pack-index" msgstr "kunde inte skriva flerpakets-index" +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "kan inte lÃ¥ta tid gÃ¥ ut för paket frÃ¥n inkrementellt multi-pack-index" + msgid "Counting referenced objects" msgstr "Räknar refererade objekt" msgid "Finding and deleting unreferenced packfiles" msgstr "Ser efter och tar bort orefererade packfiler" +msgid "cannot repack an incremental multi-pack-index" +msgstr "kunde packa om ett inkrementellt multi-pack-index" + msgid "could not start pack-objects" msgstr "kunde inte starta pack-objects" @@ -17503,6 +17751,27 @@ msgstr "paketnamnstycke för multi-pack-index är för kort" msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "paketnamn för multi-pack-index i fel ordning: â€%s†före â€%sâ€" +msgid "multi-pack-index chain file too small" +msgstr "kedjefilen för multi-pack-index är för liten" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "antalet paket i bas-MIDX för högt: %<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "antalet object i bas-MIDX för högt: %<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "ogiltig kedja för multi-pack-index: raden â€%s†är inte ett hash-värde" + +msgid "unable to find all multi-pack index files" +msgstr "kan inte hitta alla indexfiler för multi-pack" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "ogiltig MIDX-objektposition, MIDX är troligtvis trasig" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "bad pack-int-id: %u (%u paket totalt)" @@ -17520,10 +17789,6 @@ 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" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "misslyckades städa multi-pack-index pÃ¥ %s" - msgid "multi-pack-index file exists, but failed to parse" msgstr "multi-pack-indexfilen finns, men kunde inte tolkas" @@ -18011,6 +18276,17 @@ msgstr "kan inte tolka objektet: %s" msgid "hash mismatch %s" msgstr "hashvärde stämmer inte överens %s" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "duplicerad post när bitkarteindex skulle skrivas: %s" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "försökta lagra icke-vald incheckning: â€%sâ€" + +msgid "too many pseudo-merges" +msgstr "för mÃ¥nga pseudo-sammanslagningar" + msgid "trying to write commit not in index" msgstr "försöker skriva incheckning som inte finns i indexet" @@ -18033,6 +18309,20 @@ msgstr "trasigt bitkarteindex (för kort för att fÃ¥ plats för hash-cache)" msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "trasigt bitkarteindex (för kort för att fÃ¥ plats för uppslagstabell)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"trasig bitkarteindexfil (för kort för att fÃ¥ plats för pseudo-" +"sammanslagningsatbellhuvudet)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"trasig bitkarteindexfil (för kort för att fÃ¥ plats för pseudo-" +"sammanslagningstabell)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "trasig bitkarteindexfil, pseudosammanslagningstabellen är för kort" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "duplicerad post i bitkarteindex: â€%sâ€" @@ -18123,6 +18413,10 @@ msgid "mismatch in bitmap results" msgstr "bitkarteresultat stämmer inte överens" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "pseudosammanslaningsindex utenför intervallet (%<PRIu32> ≥ %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "kunde inte hitta â€%s†i paketet â€%s†pÃ¥ offset %<PRIuMAX>" @@ -18483,6 +18777,10 @@ msgstr "kan inte skapa trÃ¥dad lstat: %s" msgid "unable to parse --pretty format" msgstr "kan inte tolka format för --pretty" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "" +"fördröjd hämtning inaktiverad; nÃ¥gra objekt kanske inte är tillgängliga" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: kan inte grena (fork) av underprocessen för fetch" @@ -18507,6 +18805,71 @@ msgstr "object-info: förväntade â€flush†efter argument" msgid "Removing duplicate objects" msgstr "Tar bort duplicerade objekt" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "" +"misslyckades läsa reguljärt uttryck för pseudosammanslagning för â€%sâ€: %s" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s mÃ¥ste vara icke-negativt, använder förval" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s mÃ¥ste vara mellan 0 och 1, använder förval" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s mÃ¥ste vara positivt, använder förval" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "pseudosammanslagningsgruppen â€%s†saknar nödvändigt mönster" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"pseudosammanslagningsgruppen â€%s†har instabila tröskelvärden innan de " +"stabila" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"reguljärt uttryck för pseudosammanslagning har för mÃ¥nga fÃ¥ngstgrupper " +"(max=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"läsning utanför intervallet för utökad pseudosammanslagning (%<PRIuMAX> ≥ " +"%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"posten för utökad pseudosammanslagning är för kort (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"kunde inte hitta pseudosammanslagning för incheckningen %s pÃ¥ offset " +"%<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"uppslagning utanför intervallet för utökad pseudosammanslagning (%<PRIu32> ≥ " +"%<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "läsning utanför intervallet: (%<PRIuMAX> ≥ %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "kunde inte läsa utökad pseudosammanslagningstabell för incheckning %s" + msgid "could not start `log`" msgstr "kunde inte starta â€logâ€" @@ -18937,6 +19300,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "förväntat format: %%(ahead-behind:<incheckning-igt>)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "förväntat format: %%(is-base:<incheckning-igt>)" + +#, c-format msgid "malformed field name: %.*s" msgstr "felformat fältnamn: %.*s" @@ -19108,11 +19475,18 @@ msgstr "loggen för referensen %s slutade oväntat pÃ¥ %s" msgid "log for %s is empty" msgstr "loggen för %s är tom" +msgid "refusing to force and skip creation of reflog" +msgstr "vägrar att tvinga och hoppa över skapande av reflogg" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "vägrar uppdatera referens med trasigt namn â€%sâ€" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "vägrar uppdatera pseudoreferensen â€%sâ€" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "update_ref misslyckades för referensen â€%sâ€: %s" @@ -19143,6 +19517,32 @@ msgid "could not delete references: %s" msgstr "kunde inte ta bort referenser: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "Avslutade testkörning av referensmigrering, resultatet hittas i â€%sâ€\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "kunde ta bort temporär migreringskatalog â€%sâ€" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "migrerade referenser hittas vid â€%sâ€" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"kan inte läsa referensen â€%sâ€: förväntade symbolisk referens med mÃ¥let â€%sâ€: " +"men är en vanlig referens" + +#, c-format +msgid "cannot open directory %s" +msgstr "kunde inte öppna katalogen %s" + +msgid "Checking references consistency" +msgstr "Kontrollerar konsistens för referenser" + +#, c-format msgid "refname is dangerous: %s" msgstr "refnamnet är farligt: %s" @@ -19769,12 +20169,15 @@ msgstr "hämta endast metadata för grenen som skall checkas ut" msgid "create repository within 'src' directory" msgstr "skapa arkiv inuti katalogen â€srcâ€" +msgid "specify if tags should be fetched during clone" +msgstr "ange om taggar ska hämtas vid kloning" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <huvudgren>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enrollering>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enrollering>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -19793,6 +20196,10 @@ msgid "could not configure remote in '%s'" msgstr "kunde inte ställa in fjärr i â€%sâ€" #, c-format +msgid "could not disable tags in '%s'" +msgstr "kunde inte inaktivera taggar i â€%sâ€" + +#, c-format msgid "could not configure '%s'" msgstr "kunde inte ställa in â€%sâ€" @@ -20289,6 +20696,53 @@ msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s" msgstr "update-ref kräver ett fullständigt referensnamn, t.ex refs/heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "â€%s†godtar inte sammanslagningsincheckningar" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"â€pick†tar inte en sammanslagningsincheckning. Om du\n" +"ville spela upp sammanslagningen pÃ¥ nytt använder du\n" +"â€merge -C†pÃ¥ incheckningen." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"â€reword†tar inte en sammanslagningsincheckning. Om du\n" +"ville spela upp sammanslagningen pÃ¥ nytt och ändra texten\n" +"i incheckningsmeddelandet använder du â€merge -C†pÃ¥\n" +"incheckningen" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"â€edit†tar inte en sammanslagningsincheckning. Om du\n" +"ville spela upp sammanslagningen pÃ¥ nytt använder du\n" +"â€merge -C†pÃ¥ incheckningen och sedan â€break†för att\n" +"lämna kontrollen tillbaka till dig sÃ¥ att du kan\n" +"använda â€git commit --amend && git rebase --continueâ€." + +msgid "cannot squash merge commit into another commit" +msgstr "" +"kan inte slÃ¥ ihop en sammanslagningsincheckning med en annan incheckning" + +#, c-format msgid "invalid command '%.*s'" msgstr "ogiltigt kommando â€%.*sâ€" @@ -20406,9 +20860,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "kan inte läsa HEAD" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "kan inte kopiera in â€%s†till â€%sâ€" +msgid "could not write commit message file" +msgstr "kunde inte skriva fil för incheckningsmeddelande" #, c-format msgid "" @@ -20807,6 +21260,22 @@ msgstr "kan inte gÃ¥ tillbaka till arbetskatalogen (cwd)" msgid "failed to stat '%*s%s%s'" msgstr "misslyckades ta status pÃ¥ â€%*ss%s%sâ€" +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory â€%s†är inte absolut" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"upptäckte tveksamt ägarskap i arkivet i â€%sâ€\n" +"%sFör att lägga till ett undantag för denna katalog, kör:\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Kan inte läsa aktuell arbetskatalog" @@ -20828,18 +21297,6 @@ msgstr "" "Stoppar vid filsystemsgräns (GIT_DISCOVERY_ACROSS_FILESYSTEM är inte satt)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"upptäckte tveksamt ägarskap i arkivet i â€%sâ€\n" -"%sFör att lägga till ett undantag för denna katalog, kör:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "kan inte använda naket arkiv â€%s†(safe.bareRepository är â€%sâ€)" @@ -21141,6 +21598,16 @@ msgid "submodule git dir '%s' is inside git dir '%.*s'" msgstr "undermodul-gitkatalogen â€%s†är inuti gitkatalogen â€%.*sâ€" #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"förväntade att â€%.*s†i undermodulsökvägen â€%s†inte ska vara en symbolisk " +"länk" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "förväntade att undermodulsökvägen â€%s†inte ska vara en symbolisk länk" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -21179,10 +21646,6 @@ msgstr "misslyckades ta status (lstat) pÃ¥ â€%sâ€" msgid "no remote configured to get bundle URIs from" msgstr "ingen fjärr att hämta bunt-URI:er frÃ¥n inställd" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "fjärren â€%s†har ingen URL konfigurerad" - msgid "could not get the bundle-uri list" msgstr "kunde inte hämta bundle-uri-listan" @@ -21264,6 +21727,24 @@ msgstr "igenkänningstecken" msgid "command token to send to the server" msgstr "igenkänningstecken för kommando att sända till servern" +msgid "unit-test [<options>]" +msgstr "unit-test [<flaggor>]" + +msgid "immediately exit upon the first failed test" +msgstr "avsluta omedelbart vid det första misslyckade testet" + +msgid "suite[::test]" +msgstr "svit[::test]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "kör endast testsviten eller individuella testet <svit[::test]>" + +msgid "suite" +msgstr "svit" + +msgid "exclude test suite <suite>" +msgstr "uteslut testsviten <svit>" + #, c-format msgid "running trailer command '%s' failed" msgstr "misslyckades utföra släpradskommandot â€%sâ€" @@ -22433,6 +22914,9 @@ msgstr "â€%s.final†innehÃ¥ller det skrivna brevet.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases är inkompatibelt med andra flaggor\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases och --translate-aliases är ömsesidigt utelsutande\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -22641,24 +23125,24 @@ msgid "Failed to send %s\n" msgstr "Misslyckades sända %s\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Test-Sände %s\n" +msgid "Dry-Sent %s" +msgstr "Test-Sände %s" #, perl-format -msgid "Sent %s\n" -msgstr "Sände %s\n" +msgid "Sent %s" +msgstr "Sände %s" -msgid "Dry-OK. Log says:\n" -msgstr "Test-OK. Loggen säger:\n" +msgid "Dry-OK. Log says:" +msgstr "Test-OK. Loggen säger:" -msgid "OK. Log says:\n" -msgstr "OK. Loggen säger:\n" +msgid "OK. Log says:" +msgstr "OK. Loggen säger:" msgid "Result: " msgstr "Resultat: " -msgid "Result: OK\n" -msgstr "Resultat: OK\n" +msgid "Result: OK" +msgstr "Resultat: OK" #, perl-format msgid "can't open file %s" @@ -22733,3 +23217,10 @@ msgstr "" #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Vill du verkligen sända %s? [y=ja, n=nej]: " + +#~ msgid "revision walk setup failed\n" +#~ msgstr "misslyckades starta revisionstraversering\n" + +#, c-format +#~ msgid "unable to parse contact: %s" +#~ msgstr "kan inte tolka kontakt: %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-04-29 01:09+0300\n" -"PO-Revision-Date: 2024-04-29 01:10+0300\n" +"POT-Creation-Date: 2024-10-03 06:52+0300\n" +"PO-Revision-Date: 2024-10-03 07: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" @@ -632,7 +632,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - bu parça için sonra karar ver, bir sonraki karar verilmemiÅŸ parçayı gör\n" @@ -642,10 +642,14 @@ msgstr "" "g - gidilecek bir parça seç\n" "/ - verilen düzenli ifade ile eÅŸleÅŸen bir parça ara\n" "s - geçerli parçayı daha ufak parçalara böl\n" -"e - geçerli parçayı el ile düzenle\n" -"p - geçerli parçalı yazdır\n" +"e - geçerli parçayı elle düzenle\n" +"p - geçerli parçalı yazdır, sayfalayıcı için 'P' kullan\n" "? - yardımı yazdır\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Yalnızca bir harf bekleniyordu, '%s' alındı" + msgid "No previous hunk" msgstr "Öncesinde parça yok" @@ -694,9 +698,19 @@ msgstr "%d parçaya bölündü." msgid "Sorry, cannot edit this hunk" msgstr "Üzgünüm, bu parça düzenlenemiyor" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Bilinmeyen komut '%s' (yardım için '?')" + msgid "'git apply' failed" msgstr "'git apply' baÅŸarısız oldu" +msgid "No changes." +msgstr "DeÄŸiÅŸiklik yok." + +msgid "Only binary files changed." +msgstr "Yalnızca ikili dosyalar deÄŸiÅŸtirildi." + #, c-format msgid "" "\n" @@ -1300,6 +1314,15 @@ msgstr "ek olarak yamayı da uygula (--stat/--summary/--check ile kullan)" msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "3 yönlü birleÅŸtirme dene, baÅŸarısız olursa normal yamaya geri çekil" +msgid "for conflicts, use our version" +msgstr "çakışmalarda bizim sürümü kullan" + +msgid "for conflicts, use their version" +msgstr "çakışmalarda onların sürümünü kullan" + +msgid "for conflicts, use a union version" +msgstr "çakışmalarda birlik olmuÅŸ bir sürüm kullan" + msgid "build a temporary index based on embedded index information" msgstr "gömülü indeks bilgisini temel alan geçici bir indeks oluÅŸtur" @@ -1345,6 +1368,9 @@ msgstr "tüm dosya adlarının başına <kök> ekle" msgid "don't return error for empty patches" msgstr "boÅŸ yamalar için hata döndürme" +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs ve --union; --3way gerektiriyor" + #, c-format msgid "cannot stream blob %s" msgstr "%s ikili nesnesi akıtılamıyor" @@ -1415,6 +1441,9 @@ msgstr "geçerli bir nesne adı deÄŸil: %s" msgid "not a tree object: %s" msgstr "bir aÄŸaç nesnesi deÄŸil: %s" +msgid "unable to checkout working tree" +msgstr "çalışma aÄŸacı çıkış yapılamıyor" + #, c-format msgid "File not found: %s" msgstr "Dosya bulunamadı: %s" @@ -1545,6 +1574,9 @@ msgstr "pek büyük gitattributes dosyası '%s' dosyası yok sayılıyor" msgid "ignoring overly large gitattributes blob '%s'" msgstr "pek büyük gitattributes ikili nesnesi '%s' yok sayılıyor" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "depo olmadan --attr-source veya GIT_ATTR_SOURCE kullanılamaz" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "hatalı --attr-source veya GIT_ATTR_SOURCE" @@ -1862,13 +1894,6 @@ msgstr "%cx '%s' chmod yapılamıyor" msgid "Unstaged changes after refreshing the index:" msgstr "İndeksi yeniledikten sonra hazırlanmamış deÄŸiÅŸiklikler:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"add.interactive.useBuiltin ayarı kaldırıldı!\n" -"Ayrıntılar için onun 'git help config' içindeki girdisine bakın." - msgid "could not read the index" msgstr "indeks okunamadı" @@ -1979,7 +2004,7 @@ msgid "adding embedded git repository: %s" msgstr "gömülü git deposu ekleniyor: %s" msgid "Use -f if you really want to add them." -msgstr "Onları gerçekten eklemek istiyorsanız -f kullanın." +msgstr "Onları eklemeyi gerçekten istiyorsanız -f kullanın." msgid "adding files failed" msgstr "dosya ekleme baÅŸarısız" @@ -2310,6 +2335,9 @@ msgstr "yamalama iÅŸlemini iptal et; ancak HEAD'i olduÄŸu yerde bırak" msgid "show the patch being applied" msgstr "uygulanmakta olan yamayı göster" +msgid "try to apply current patch again" +msgstr "yeniden geçerli yamayı uygulamaya çalış" + msgid "record the empty patch as an empty commit" msgstr "boÅŸ yamayı bir boÅŸ iÅŸleme olarak kayıt yaz" @@ -2366,9 +2394,6 @@ msgstr "git apply [<seçenekler>] [<yama>...]" msgid "could not redirect output" msgstr "çıktı yeniden yönlendirilemedi" -msgid "git archive: Remote with no URL" -msgstr "git archive: URL'si olmayan uzak konum" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: ACK/NAK bekleniyordu, floÅŸ paketi alındı" @@ -2521,9 +2546,6 @@ msgstr "" "'git bisect terms' için geçersiz argüman %s.\n" "Desteklenen seçenekler: --term-good|--term-old ve --term-bad|--term-new." -msgid "revision walk setup failed\n" -msgstr "revizyonda gezinme ayarlaması baÅŸarısız oldu\n" - #, c-format msgid "could not open '%s' for appending" msgstr "'%s' iliÅŸtirme için açılamadı" @@ -3261,6 +3283,9 @@ msgstr "Bir demet oluÅŸturmak için bir depo gerekli." msgid "do not show bundle details" msgstr "demet ayrıntılarını gösterme" +msgid "need a repository to verify a bundle" +msgstr "bir demeti doÄŸrulamak için bir depo gerekiyor" + #, c-format msgid "%s is okay\n" msgstr "%s tamam\n" @@ -3495,9 +3520,14 @@ msgstr "git check-mailmap [<seçenekler>] <kiÅŸi>..." msgid "also read contacts from stdin" msgstr "stdin'den kiÅŸileri de oku" -#, c-format -msgid "unable to parse contact: %s" -msgstr "kiÅŸi ayrıştırılamadı: %s" +msgid "read additional mailmap entries from file" +msgstr "dosyadan ek mailmap girdilerini oku" + +msgid "blob" +msgstr "ikili nesne" + +msgid "read additional mailmap entries from blob" +msgstr "ikili nesneden ek mailmap girdilerini oku" msgid "no contacts specified" msgstr "kiÅŸi belirtilmedi" @@ -3845,6 +3875,10 @@ msgid "'%s' cannot be used with switching branches" msgstr "dal deÄŸiÅŸtirilirken '%s' kullanılamaz" #, c-format +msgid "'%s' needs the paths to check out" +msgstr "çıkış yapmak için '%s' yollara gereksinim duyuyor" + +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s', '%s' ile birlikte kullanılamaz" @@ -4272,6 +4306,14 @@ 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ı" @@ -4313,9 +4355,6 @@ 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" @@ -4601,7 +4640,7 @@ msgstr "git commit-tree: okunamadı" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4610,14 +4649,14 @@ msgid "" " [--] [<pathspec>...]" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<kip>] [--amend]\n" -" [--dry-run] [(-c | -C | --squash) <iÅŸleme> | --fixup [(amend|" -"reword):]<iÅŸleme>)]\n" -" [-F <dosya> | -m <ileti>] [--reset-author] [--allow-empty]\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" " [--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" -" [--] [<yol-blrtç>...]" +" [--] [<yol-belirteci>...]" msgid "git status [<options>] [--] [<pathspec>...]" msgstr "git status [<seçenekler>] [--] [<yol-blrtç>...]" @@ -5104,15 +5143,58 @@ msgstr "" "Diskin dolu olup olmadığını ve kotanızı aşıp aÅŸmadığınızı denetleyin,\n" "sonra kurtarmak için \"git restore --staged :/\" kullanın." -msgid "git config [<options>]" -msgstr "git config [<seçenekler>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "" +"git config list [<dosya-seçeneÄŸi>] [<görüntüleme-seçeneÄŸi>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "tanımlanamayan --type argümanı, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<dosya-sçnÄŸi>] [<görüntü-sçnÄŸi>] [--includes] [--all] [--" +"regexp] [--value=<deÄŸer>] [--fixed-value] [--default=<öntanımlı>] <ad>" -msgid "only one type at a time" -msgstr "bir kerede yalnızca bir tür" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<dosya-seçeneÄŸi>] [--type=<tür>] [--all] [--value=<deÄŸer>] " +"[--fixed-value] <ad> <deÄŸer>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<dosya-seçeneÄŸi>] [--all] [--value=<deÄŸer>] [--fixed-" +"value] <ad> <deÄŸer>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<dosya-seçeneÄŸi>] <eski-ad> <yeni-ad>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<dosya-seçeneÄŸi>] <ad>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<dosya-seçeneÄŸi>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<dosya-seçeneÄŸi>] --get-colorbool <ad> [<stdout-tty>]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<dosya-seçeneÄŸi>] [<görüntüleme-seçeneÄŸi>] [--includes] [--" +"all] [--regexp=<düzenli-ifade>] [--value=<deÄŸer>] [--fixed-value] [--" +"default=<öntanımlı>] <ad>" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<dosya-seçeneÄŸi>] [--type=<tür>] [--comment=<ileti>] [--all] " +"[--value=<deÄŸer>] [--fixed-value] <ad> <deÄŸer>" msgid "Config file location" msgstr "Yapılandırma dosyası konumu" @@ -5138,54 +5220,6 @@ msgstr "ikili nesne numarası" msgid "read config from given blob object" msgstr "verilen ikili nesneden yapılandırmayı oku" -msgid "Action" -msgstr "Eylem" - -msgid "get value: name [value-pattern]" -msgstr "deÄŸer al: ad [deÄŸer-dizgisi]" - -msgid "get all values: key [value-pattern]" -msgstr "tüm deÄŸerleri al: anahtar [deÄŸer-dizgisi]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "düzenli ifade için deÄŸerleri al: düzenli ifade adı [deÄŸer-dizgisi]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "URL için özel olan deÄŸeri al: bölüm[.var] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "tüm eÅŸleÅŸen deÄŸiÅŸkenleri deÄŸiÅŸtir: ad deÄŸer [deÄŸer-dizgisi]" - -msgid "add a new variable: name value" -msgstr "yeni bir deÄŸiÅŸken ekle: ad deÄŸer" - -msgid "remove a variable: name [value-pattern]" -msgstr "bir deÄŸiÅŸken kaldır: ad [deÄŸer-dizgisi]" - -msgid "remove all matches: name [value-pattern]" -msgstr "tüm eÅŸleÅŸmeleri kaldır: ad [deÄŸer-dizgisi]" - -msgid "rename section: old-name new-name" -msgstr "bölümü yeniden adlandır: eski-ad yeni-ad" - -msgid "remove a section: name" -msgstr "bir bölümü kaldır: ad" - -msgid "list all" -msgstr "tümünü listele" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "deÄŸerleri 'deÄŸer-dizgisi' ile karşılaÅŸtırırken dizi eÅŸitliÄŸi kullan" - -msgid "open an editor" -msgstr "bir düzenleyici aç" - -msgid "find the color configured: slot [default]" -msgstr "yapılandırılan rengi bul: yuva [öntanımlı]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "renk ayarını bul: yuva [stdout tty]" - msgid "Type" msgstr "Tür" @@ -5213,8 +5247,8 @@ msgstr "deÄŸer bir yol (dosya veya dizin adı)" msgid "value is an expiry date" msgstr "deÄŸer bir son kullanım tarihi" -msgid "Other" -msgstr "DiÄŸer" +msgid "Display options" +msgstr "Seçenekleri görüntüle" msgid "terminate values with NUL byte" msgstr "deÄŸerleri NUL baytı ile sonlandır" @@ -5222,9 +5256,6 @@ msgstr "deÄŸerleri NUL baytı ile sonlandır" msgid "show variable names only" msgstr "yalnızca deÄŸiÅŸken adlarını göster" -msgid "respect include directives on lookup" -msgstr "arama sırasında içerme yönergelerine uy" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "yapılandırmanın kökenini göster (dosya, stdin, ikili nesne, komut satırı)" @@ -5234,14 +5265,15 @@ msgstr "" "yapılandırmanın kapsamını göster (çalışma aÄŸacı, yerel, global, sistem, " "komut)" -msgid "value" -msgstr "deÄŸer" +msgid "show config keys in addition to their values" +msgstr "deÄŸerlerine ek olarak yapılandırma anahtarlarını da göster" -msgid "with --get, use default value when missing entry" -msgstr "--get ile girdi verilmemiÅŸse öntanımlı deÄŸeri kullan" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "tanımlanamayan --type argümanı, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "kiÅŸi tarafından okunabilir yorum satırı (gerekirse önüne # koyulur)" +msgid "only one type at a time" +msgstr "bir kerede yalnızca bir tür" #, c-format msgid "wrong number of arguments, should be %d" @@ -5317,47 +5349,72 @@ msgstr "" "sürece birden çok çalışma aÄŸacı ile birlikte kullanılamaz. Ayrıntılar için\n" "lütfen \"git help worktree\" içindeki \"CONFIGURATION FILE\" bölümünü okuyun" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color ve deÄŸiÅŸken türü tutarsız" +msgid "Other" +msgstr "DiÄŸer" -msgid "only one action at a time" -msgstr "bir kerede yalnızca bir eylem" +msgid "respect include directives on lookup" +msgstr "arama sırasında içerme yönergelerine uy" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only yalnızca ÅŸunlara uygulanabilir: --list, --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "'%s' yapılandırma dosyası okunamıyor" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"--show-origin yalnızca ÅŸunlara uygulanabilir: --get, --get-all, --get-regexp " -"ve --list" +msgid "error processing config file(s)" +msgstr "yapılandırma dosyaları iÅŸlenirken hata" -msgid "--default is only applicable to --get" -msgstr "--default yalnızca --get için uygulanabilir" +msgid "Filter options" +msgstr "Süzme seçenekleri" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment yalnızca ekle/ayarla/deÄŸiÅŸtir iÅŸlemlerine uygulanabilir" +msgid "return all values for multi-valued config options" +msgstr "birden çok deÄŸerli yapılandırma seçeneklerinin tüm deÄŸerlerini döndür" + +msgid "interpret the name as a regular expression" +msgstr "adı düzenli ifade olarak yorumla" + +msgid "show config with values matching the pattern" +msgstr "dizgiyle eÅŸleÅŸen deÄŸerleri olan yapılandırmayı göster" + +msgid "use string equality when comparing values to value pattern" +msgstr "deÄŸerleri deÄŸer dizgisiyle karşılaÅŸtırırken dizi eÅŸitliÄŸini kullan" + +msgid "URL" +msgstr "URL" + +msgid "show config matching the given URL" +msgstr "verilen URL ile eÅŸleÅŸen yapılandırmayı göster" + +msgid "value" +msgstr "deÄŸer" + +msgid "use default value when missing entry" +msgstr "girdi eksikse öntanımlı deÄŸeri kullan" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value yalnızca 'deÄŸer-dizgisi' ile uygulanır" -#, c-format -msgid "unable to read config file '%s'" -msgstr "'%s' yapılandırma dosyası okunamıyor" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default=, --all veya --url= ile kullanılamaz" -msgid "error processing config file(s)" -msgstr "yapılandırma dosyaları iÅŸlenirken hata" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url=; --all, --regexp veya --value ile kullanılamaz" -msgid "editing stdin is not supported" -msgstr "stdin'i düzenleme desteklenmiyor" +msgid "Filter" +msgstr "Süzgeç" -msgid "editing blobs is not supported" -msgstr "ikili nesneleri düzenleme desteklenmiyor" +msgid "replace multi-valued config option with new value" +msgstr "birden çok deÄŸerli yapılandırma seçeneÄŸini yeni deÄŸerle deÄŸiÅŸtir" -#, c-format -msgid "cannot create configuration file %s" -msgstr "%s yapılandırma dosyası oluÅŸturulamıyor" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "kiÅŸi tarafından okunabilir yorum satırı (gerekirse önüne # koyulur)" + +msgid "add a new line without altering any existing values" +msgstr "var olan herhangi deÄŸeri deÄŸiÅŸtirmeden yeni satır ekle" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value, yalnızca --value=<dizgi> ile geçerlidir" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append, --value=<dizgi> ile kullanılamaz" #, c-format msgid "" @@ -5372,6 +5429,86 @@ msgstr "" msgid "no such section: %s" msgstr "böyle bir bölüm yok: %s" +msgid "editing stdin is not supported" +msgstr "stdin'i düzenleme desteklenmiyor" + +msgid "editing blobs is not supported" +msgstr "ikili nesneleri düzenleme desteklenmiyor" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "%s yapılandırma dosyası oluÅŸturulamıyor" + +msgid "Action" +msgstr "Eylem" + +msgid "get value: name [<value-pattern>]" +msgstr "deÄŸer al: ad [<deÄŸer-dizgisi>]" + +msgid "get all values: key [<value-pattern>]" +msgstr "tüm deÄŸerleri al: anahtar [<deÄŸer-dizgisi>]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "düzenli ifade için deÄŸerleri al: düzenli ifade adı [<deÄŸer-dizgisi>]" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "URL için özel olan deÄŸeri al: bölüm[.var] URL" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "tüm eÅŸleÅŸen deÄŸiÅŸkenleri deÄŸiÅŸtir: ad deÄŸer [<deÄŸer-dizgisi>]" + +msgid "add a new variable: name value" +msgstr "yeni bir deÄŸiÅŸken ekle: ad deÄŸer" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "bir deÄŸiÅŸken kaldır: ad [<deÄŸer-dizgisi>]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "tüm eÅŸleÅŸmeleri kaldır: ad [<deÄŸer-dizgisi>]" + +msgid "rename section: old-name new-name" +msgstr "bölümü yeniden adlandır: eski-ad yeni-ad" + +msgid "remove a section: name" +msgstr "bir bölümü kaldır: ad" + +msgid "list all" +msgstr "tümünü listele" + +msgid "open an editor" +msgstr "bir düzenleyici aç" + +msgid "find the color configured: slot [<default>]" +msgstr "yapılandırılan rengi bul: yuva [<öntanımlı>]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "renk ayarını bul: yuva [<stdout-tty>]" + +msgid "with --get, use default value when missing entry" +msgstr "--get ile girdi verilmemiÅŸse öntanımlı deÄŸeri kullan" + +msgid "--get-color and variable type are incoherent" +msgstr "--get-color ve deÄŸiÅŸken türü tutarsız" + +msgid "no action specified" +msgstr "belirtilen eylem yok" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only yalnızca ÅŸunlara uygulanabilir: --list, --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin yalnızca ÅŸunlara uygulanabilir: --get, --get-all, --get-regexp " +"ve --list" + +msgid "--default is only applicable to --get" +msgstr "--default yalnızca --get için uygulanabilir" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment yalnızca ekle/ayarla/deÄŸiÅŸtir iÅŸlemlerine uygulanabilir" + msgid "print sizes in human readable format" msgstr "yazdırma boyutları kiÅŸi tarafından okunabilir biçimde" @@ -5854,8 +5991,8 @@ msgstr "" "bu denetlemeden kaçınabilirsiniz.\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s tüm gerekli nesneleri göndermedi\n" +msgid "%s did not send all necessary objects" +msgstr "%s tüm gerekli nesneleri göndermedi" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -5892,8 +6029,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "\"%s\" seçeneÄŸi \"%s\" deÄŸeri %s için geçerli deÄŸil" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "\"%s\" seçeneÄŸi %s için yok sayılıyor\n" +msgid "option \"%s\" is ignored for %s" +msgstr "\"%s\" seçeneÄŸi %s için yok sayılıyor" #, c-format msgid "%s is not a valid object" @@ -6194,6 +6331,9 @@ msgstr "yapılandırma" msgid "config key storing a list of repository paths" msgstr "bir depo yolları listesi tutan yapılandırma anahtarı" +msgid "keep going even if command fails in a repository" +msgstr "komut depoda baÅŸarısız olsa bile gitmeyi sürdür" + msgid "missing --config=<config>" msgstr "--config=<yapılandırma> eksik" @@ -6563,6 +6703,9 @@ msgstr "biraz daha titiz ol (artırılmış iÅŸleyiÅŸ süresi)" msgid "enable auto-gc mode" msgstr "auto-gc kipini etkinleÅŸtir" +msgid "perform garbage collection in the background" +msgstr "çöp toplamayı arka planda gerçekleÅŸtir" + msgid "force running gc even if there may be another gc running" msgstr "baÅŸka bir gc çalışıyor olsa bile zorla gc çalıştır" @@ -6658,6 +6801,9 @@ msgstr "'%s' görevi birden çok kez seçilemez" msgid "run tasks based on the state of the repository" msgstr "görevleri deponun durumuna göre çalıştır" +msgid "perform maintenance in the background" +msgstr "bakımı arka planda gerçekleÅŸtir" + msgid "frequency" msgstr "sıklık" @@ -7520,9 +7666,6 @@ msgstr "-L<erim>:<dosya>, yol belirteci ile kullanılamıyor" msgid "Final output: %d %s\n" msgstr "Son çıktı: %d %s\n" -msgid "unable to create temporary object directory" -msgstr "geçici nesne dizini oluÅŸturulamıyor" - #, c-format msgid "git show %s: bad file" msgstr "git show %s: hatalı dosya" @@ -7645,8 +7788,11 @@ msgstr "diziyi n. deneme olarak imle" msgid "max length of output filename" msgstr "çıktı dosya adının olabilecek en çok uzunluÄŸu" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "[PATCH] yerine [RFC PATCH] kullan" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "'PATCH' öncesi <rfc> ekle (öntanımlı 'RFC')" msgid "cover-from-description-mode" msgstr "açıklama kipinden kapak sayfası kipi" @@ -7909,11 +8055,12 @@ msgstr "" "kullanılamaz" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<yürütülebilir>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-" +"pack=<yürütülebilir>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<anahtar>]\n" " [--symref] [<depo> [<dizgiler>...]]" @@ -7929,8 +8076,11 @@ msgstr "uzak konum makinesindeki git-upload-pack yolu" msgid "limit to tags" msgstr "etiketlere kısıtla" -msgid "limit to heads" -msgstr "uç iÅŸlemelere kısıtla" +msgid "limit to branches" +msgstr "dallara kısıtla" + +msgid "deprecated synonym for --branches" +msgstr "--branches için artık kullanılmayan eÅŸanlamlı" msgid "do not show peeled tags" msgstr "soyulmuÅŸ etiketleri gösterme" @@ -8077,15 +8227,6 @@ msgstr "diff3 tabanlı birleÅŸtirme kullan" msgid "use a zealous diff3 based merge" msgstr "gayretli bir diff3 tabanlı birleÅŸtirme kullan" -msgid "for conflicts, use our version" -msgstr "çakışmalarda bizim sürümü kullan" - -msgid "for conflicts, use their version" -msgstr "çakışmalarda onların sürümünü kullan" - -msgid "for conflicts, use a union version" -msgstr "çakışmalarda birlik olmuÅŸ bir sürüm kullan" - msgid "<algorithm>" msgstr "<algoritma>" @@ -8548,6 +8689,9 @@ msgstr "bir çoklu paket biteÅŸlemi hesaplanırken yeniden kullanılacak paket" msgid "write multi-pack bitmap" msgstr "çoklu paket biteÅŸlemi yaz" +msgid "write a new incremental MIDX" +msgstr "yeni bir artımlı MIDX yaz" + msgid "write multi-pack index containing only given indexes" msgstr "yalnızca verilen indeksleri içeren çoklu paket indekslerini yaz" @@ -10553,6 +10697,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +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 "missing --ref-format=<format>" +msgstr "--ref-format=<biçim> eksik" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "depo halihazırda '%s' biçimini kullanıyor" + +msgid "enable strict checking" +msgstr "kesin denetlemeyi etkinleÅŸtir" + +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' bir argüman almıyor" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -10838,9 +11007,6 @@ msgstr "* uzak konum %s" msgid " Fetch URL: %s" msgstr " URL'yi getir: %s" -msgid "(no URL)" -msgstr "(URL yok)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -10849,6 +11015,9 @@ msgstr "(URL yok)" msgid " Push URL: %s" msgstr " URL'yi it: %s" +msgid "(no URL)" +msgstr "(URL yok)" + #, c-format msgid " HEAD branch: %s" msgstr " HEAD dalı: %s" @@ -10955,10 +11124,6 @@ msgstr "itme URL'lerinden çok getirme URL'lerini sorgula" msgid "return all URLs" msgstr "tüm URL'leri döndür" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "'%s' uzak konumu için URL yapılandırılmamış" - msgid "manipulate push URLs" msgstr "itme URL'lerini deÄŸiÅŸtir" @@ -11959,12 +12124,12 @@ msgstr "bilinmeyen saÄŸlama algoritması '%s'" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<dizgi>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<dizgi>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -11987,11 +12152,11 @@ msgstr "baÅŸvuru yok" msgid "failed to look up reference" msgstr "baÅŸvuru bakılamadı" -msgid "only show tags (can be combined with heads)" -msgstr "yalnızca etiketleri göster (dal uçlarıyla birlikte kullanılabilir)" +msgid "only show tags (can be combined with --branches)" +msgstr "yalnızca etiketleri göster (--branches ile birlikte kullanılabilir)" -msgid "only show heads (can be combined with tags)" -msgstr "yalnızca dal uçlarını göster (etiketlerle birlikte kullanılabilir)" +msgid "only show branches (can be combined with --tags)" +msgstr "yalnızca dalları göster (--tags ile birlikte kullanılabilir)" msgid "check for reference existence without resolving" msgstr "çözmeden baÅŸvuru varlığını denetle" @@ -12043,6 +12208,10 @@ msgstr "'%s' dizini kaldırılamadı" msgid "failed to create directory for sparse-checkout file" msgstr "aralıklı çıkış dosyası için dizin oluÅŸturulamadı" +#, c-format +msgid "unable to fdopen %s" +msgstr "%s fdopen yapılamıyor" + msgid "failed to initialize worktree config" msgstr "çalışma aÄŸacı yapılandırması ilklendirilemedi" @@ -12491,8 +12660,8 @@ msgid "couldn't hash object from '%s'" msgstr "'%s' üzerinden nesne saÄŸlaması yapılamadı" #, c-format -msgid "unexpected mode %o\n" -msgstr "beklenmedik kip %o\n" +msgid "unexpected mode %o" +msgstr "beklenmedik kip %o" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "altmodül HEAD'i içindeki iÅŸleme ile indekstekini karşılaÅŸtırmak için" @@ -12611,14 +12780,14 @@ msgstr "" "baÅŸka bir altmodülün git dizininde '%s' oluÅŸturma/kullanma reddediliyor" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "'%s' ögesinin '%s' altmodül yoluna klonlanması baÅŸarısız" - -#, c-format msgid "directory not empty: '%s'" msgstr "dizin boÅŸ deÄŸil: '%s'" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "'%s' ögesinin '%s' altmodül yoluna klonlanması baÅŸarısız" + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "'%s' için altmodül dizini alınamadı" @@ -12975,10 +13144,12 @@ msgstr "güncelleme nedeni" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <anahtar-kimliÄŸi>] [-f] [-m <ileti> | -F <dosya>] [-" "e]\n" +" [(--trailer <jeton>[(=|:)<deÄŸer>])...]\n" " <etiket-adı> [<iÅŸleme> | <nesne>]" msgid "git tag -d <tagname>..." @@ -13324,8 +13495,8 @@ msgid "" "core.untrackedCache is set to true; remove or change it, if you really want " "to disable the untracked cache" msgstr "" -"core.untrackedCache 'true' olarak ayarlanmış; izlenmeyen önbelleÄŸi gerçekten " -"devre dışı bırakmayı istiyorsanız bunu kaldırın veya deÄŸiÅŸtirin" +"core.untrackedCache 'true' olarak ayarlanmış; izlenmeyen önbelleÄŸi devre " +"dışı bırakmayı gerçekten istiyorsanız bunu kaldırın veya deÄŸiÅŸtirin" msgid "Untracked cache disabled" msgstr "İzlenmeyen önbellek devre dışı bırakıldı" @@ -13335,7 +13506,7 @@ msgid "" "to enable the untracked cache" msgstr "" "core.untrackedCache 'false' olarak ayarlanmış; izlenmeyen önbelleÄŸi " -"gerçekten etkinleÅŸtirmek istiyorsanız bunu kaldırın veya deÄŸiÅŸtirin" +"etkinleÅŸtirmeyi gerçekten istiyorsanız bunu kaldırın veya deÄŸiÅŸtirin" #, c-format msgid "Untracked cache enabled for '%s'" @@ -13343,8 +13514,8 @@ msgstr "İzlenmeyen önbellek '%s' için etkinleÅŸtirildi" msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor" msgstr "" -"core.fsmonitor ayarlanmamış; dosya sistemin monitörünü gerçekten " -"etkinleÅŸtirmek istiyorsanız onu ayarlayın" +"core.fsmonitor ayarlanmamış; dosya sistemin monitörünü etkinleÅŸtirmeyi " +"gerçekten istiyorsanız onu ayarlayın" msgid "fsmonitor enabled" msgstr "dosya sistemi monitörü etkin" @@ -13352,8 +13523,8 @@ msgstr "dosya sistemi monitörü etkin" msgid "" "core.fsmonitor is set; remove it if you really want to disable fsmonitor" msgstr "" -"core.fsmonitor ayarlanmış; dosya sistemi monitörünü gerçekten devre dışı " -"bırakmak istiyorsanız onu kaldırın" +"core.fsmonitor ayarlanmış; dosya sistemi monitörünü devre dışı bırakmayı " +"gerçekten istiyorsanız onu kaldırın" msgid "fsmonitor disabled" msgstr "dosya sistemi monitörü devre dışı" @@ -13818,9 +13989,6 @@ msgstr "tanımlanamayan üstbilgi: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Depo aÅŸağıdaki önkoÅŸul iÅŸlemelere iye deÄŸil:" -msgid "need a repository to verify a bundle" -msgstr "bir demeti doÄŸrulamak için bir depo gerekiyor" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14217,6 +14385,9 @@ msgstr "Depoya ne itildiyse al" msgid "Manage reflog information" msgstr "BaÅŸvuru günlüğü bilgisini yönet" +msgid "Low-level access to refs" +msgstr "BaÅŸvurulara alt düzeyden eriÅŸim" + msgid "Manage set of tracked repositories" msgstr "İzlenen depolar setini yönet" @@ -14521,6 +14692,14 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "" "commit-graph'ten gerekli OID çıkış sayısı iri parçası eksik veya hasarlı" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"uyumsuz ayarlardan dolayı '%s' commit-graph katmanı için olan Bloom " +"süzgeçleri devre dışı bırakılıyor" + msgid "commit-graph has no base graphs chunk" msgstr "commit-graph temel grafiÄŸi iri parçasına iye deÄŸil" @@ -14645,6 +14824,14 @@ msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "" "bir commit-graph yazılmaya çalışılıyor; ancak 'core.commitGraph' devre dışı" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"bir commit-graph yazılmaya çalışılıyor; ancak 'commitGraph." +"changedPathsVersion' (%d) desteklenmiyor" + msgid "too many commits to write graph" msgstr "grafik yazımı için pek fazla iÅŸleme" @@ -16488,17 +16675,21 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <yol>] [-c <ad>=<deÄŸer>]\n" " [--exec-path[=<yol>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<yol>] [--work-tree=<yol>] [--namespace=<ad>]\n" -" [--config-env=<ad>=<çevre-deÄŸiÅŸkeni>] <komut> [<argümanlar>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<ad>] [--config-env=<ad>=<çevre-" +"deÄŸiÅŸkeni>]\n" +" <komut> [<argümanlar>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -16838,13 +17029,13 @@ msgstr "" "'%s' kancası yok sayıldı; çünkü bir yürütülebilir olarak ayarlanmamış.\n" "Bu uyarıyı 'git config advice.ignoredHook false' ile kapatabilirsiniz." +msgid "not a git repository" +msgstr "bir git deposu deÄŸil" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "--packfile için argüman geçerli bir saÄŸlama olmalıdır ('%s' alındı)" -msgid "not a git repository" -msgstr "bir git deposu deÄŸil" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "http.postBuffer için negatif deÄŸer; %d olarak varsayılıyor" @@ -16855,6 +17046,9 @@ msgstr "Delegasyon denetimi cURL < 7.22.0 tarafından desteklenmiyor" msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "Ortak anahtar iÄŸnelemesi cURL < 7.39.0 tarafından desteklenmiyor" +msgid "Unknown value for http.proactiveauth" +msgstr "http.proactiveauth için bilinmeyen deÄŸer" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE cURL < 7.44.0 tarafından desteklenmiyor" @@ -16871,6 +17065,12 @@ msgstr "" msgid "Could not set SSL backend to '%s': already set" msgstr "SSL arka ucu '%s' olarak ayarlanamadı: Halihazırda ayarlanmış" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "http.cookiefile '-' konumundan çerezleri okuma reddediliyor" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "boÅŸ http.cookiefile için http.savecookies yok sayılıyor" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17012,13 +17212,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "'%s.lock' oluÅŸturulamıyor: %s" +msgid "unable to create temporary object directory" +msgstr "geçici nesne dizini oluÅŸturulamıyor" + #, c-format msgid "could not write loose object index %s" msgstr "gevÅŸek nesne indeksi %s yazılamadı" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "gevÅŸek nesne indeksi %s yazımı baÅŸarısız\n" +msgid "failed to write loose object index %s" +msgstr "gevÅŸek nesne indeksi %s yazılamadı" #, c-format msgid "unexpected line: '%s'" @@ -17047,8 +17250,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "%s altmodülü birleÅŸtirilemedi (iÅŸlemeler yok)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "%s altmodülü birleÅŸtirilemedi (depo hasarlı)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "hata: %s altmodülü birleÅŸtirilemedi (depo hasarlı)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17076,12 +17279,13 @@ msgstr "" "%s altmodülü birleÅŸtirilemedi; ancak birden çok olası birleÅŸtirmeler var:\n" "%s" -msgid "failed to execute internal merge" -msgstr "iç birleÅŸtirme yürütülemedi" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "hata: %s için iç birleÅŸtirme yürütülemedi" #, c-format -msgid "unable to add %s to database" -msgstr "%s veritabanına eklenemiyor" +msgid "error: unable to add %s to database" +msgstr "hata: %s veritabanına eklenemiyor" #, c-format msgid "Auto-merging %s" @@ -17178,12 +17382,12 @@ msgstr "" "ancak %s içinde silindi." #, c-format -msgid "cannot read object %s" -msgstr "%s nesnesi okunamıyor" +msgid "error: cannot read object %s" +msgstr "hata: %s nesnesi okunamıyor" #, c-format -msgid "object %s is not a blob" -msgstr "%s nesnesi ikili bir nesne deÄŸil" +msgid "error: object %s is not a blob" +msgstr "hata: %s nesnesi ikili bir nesne deÄŸil" #, c-format msgid "" @@ -17322,6 +17526,10 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "ÅŸununla ne yapılacağı bilinmiyor: %06o %s '%s'" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "%s altmodülü birleÅŸtirilemedi (depo hasarlı)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "%s altmodülü ÅŸu iÅŸlemeye ileri sarılıyor:" @@ -17360,6 +17568,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "%s altmodülü birleÅŸtirilemedi (birden çok birleÅŸtirme bulundu)" +msgid "failed to execute internal merge" +msgstr "iç birleÅŸtirme yürütülemedi" + +#, c-format +msgid "unable to add %s to database" +msgstr "%s veritabanına eklenemiyor" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -17464,6 +17679,14 @@ msgstr "" "ÇAKIÅžMA (y. adlandır/y. adlandır): Dizini %s->%s olarak adlandır (%s " "içinde). Dizini %s->%s olarak adlandır (%s içinde)" +#, c-format +msgid "cannot read object %s" +msgstr "%s nesnesi okunamıyor" + +#, c-format +msgid "object %s is not a blob" +msgstr "%s nesnesi ikili bir nesne deÄŸil" + msgid "modify" msgstr "deÄŸiÅŸtir" @@ -17547,9 +17770,6 @@ msgstr "satır ayrıştırılamadı: %s" msgid "malformed line: %s" msgstr "hatalı oluÅŸturulmuÅŸ satır: %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "var olan multi-pack-index yok sayılıyor; saÄŸlama toplamı uyumsuzluÄŸu" - msgid "could not load pack" msgstr "paket yüklenemedi" @@ -17557,6 +17777,20 @@ msgstr "paket yüklenemedi" msgid "could not open index for %s" msgstr "%s için indeks açılamadı" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "'%s', '%s' ile baÄŸlantılanamıyor" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "multi-pack-index %s konumunda temizlenemedi" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "biteÅŸlem ile artımlı MIDX yazılamıyor" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "var olan multi-pack-index yok sayılıyor; saÄŸlama toplamı uyumsuzluÄŸu" + msgid "Adding packfiles to multi-pack-index" msgstr "Paket dosyaları multi-pack-index'e ekleniyor" @@ -17582,18 +17816,34 @@ msgstr "indekslenecek paket dosyası yok." msgid "refusing to write multi-pack .bitmap without any objects" msgstr "bir nesne olmadan multi-pack .bitmap yazımı reddediliyor" +msgid "unable to create temporary MIDX layer" +msgstr "geçici MIDX katmanı oluÅŸturulamıyor" + msgid "could not write multi-pack bitmap" msgstr "çoklu paket biteÅŸlem yazılamadı" +msgid "unable to open multi-pack-index chain file" +msgstr "multi-pack-index zincir dosyası açılamıyor" + +msgid "unable to rename new multi-pack-index layer" +msgstr "yeni multi-pack-index katmanı yeniden adlandırılamıyor" + msgid "could not write multi-pack-index" msgstr "multi-pack-index yazılamadı" +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "" +"artımlı bir multi-pack-index ögesinden paketlerin süresi doldurulamıyor" + msgid "Counting referenced objects" msgstr "BaÅŸvurulmuÅŸ nesneler sayılıyor" msgid "Finding and deleting unreferenced packfiles" msgstr "BaÅŸvurulmamış paket dosyaları bulunuyor ve siliniyor" +msgid "cannot repack an incremental multi-pack-index" +msgstr "artımlı bir multi-pack-index yeniden paketlenemiyor" + msgid "could not start pack-objects" msgstr "pack-objects baÅŸlatılamadı" @@ -17651,6 +17901,27 @@ msgstr "multi-pack-index pack-name iri parçası pek kısa" msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "multi-pack-index paket adlarının sırasız: '%s' ÅŸundan önce: '%s'" +msgid "multi-pack-index chain file too small" +msgstr "multi-pack-index zincir dosyası pek küçük" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "temel MIDX içindeki paket sayısı pek yüksek: %<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "temel MIDX içindeki nesne sayısı pek yüksek: %<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "geçersiz multi-pack-index zinciri: '%s' bir saÄŸlama deÄŸil" + +msgid "unable to find all multi-pack index files" +msgstr "tüm multi-pack-index dosyaları bulunamıyor" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "geçersiz MIDX nesnesi konumu, MIDX büyük olasılıkla hasarlı" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "hatalı pack-int-id: %u (%u toplam paket)" @@ -17668,10 +17939,6 @@ msgstr "multi-pack-index bir 64 bit ofset depoluyor; ancak off_t pek küçük" msgid "multi-pack-index large offset out of bounds" msgstr "multi-pack-index geniÅŸ ofseti sınırlar dışında" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "multi-pack-index %s konumunda temizlenemedi" - msgid "multi-pack-index file exists, but failed to parse" msgstr "multi-pack-index dosyası var; ancak ayrıştırılamadı" @@ -17880,6 +18147,14 @@ msgid "missing mapping of %s to %s" msgstr "%s ögesinin %s ögesine eksik eÅŸlemlemesi" #, c-format +msgid "unable to open %s" +msgstr "%s açılamıyor" + +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "'%s' ve '%s' dosyalarının içeriÄŸi farklı" + +#, c-format msgid "unable to write file %s" msgstr "%s dosyası yazılamıyor" @@ -17964,10 +18239,6 @@ msgid "%s is not a valid '%s' object" msgstr "%s geçerli bir '%s' nesnesi deÄŸil" #, c-format -msgid "unable to open %s" -msgstr "%s açılamıyor" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s için saÄŸlama uyuÅŸmazlığı (%s bekleniyordu)" @@ -18160,6 +18431,17 @@ msgstr "nesne ayrıştırılamıyor: %s" msgid "hash mismatch %s" msgstr "saÄŸlama uyuÅŸmazlığı %s" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "biteÅŸlem indeksi yazılırken yinelenen girdi: %s" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "seçili olmayan iÅŸleme yazılmaya çalışıldı: '%s'" + +msgid "too many pseudo-merges" +msgstr "pek çok yalancı birleÅŸtirme" + msgid "trying to write commit not in index" msgstr "indekste olmayan iÅŸleme yazılmaya çalışılıyor" @@ -18184,6 +18466,20 @@ msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "" "hasarlı biteÅŸlem indeks dosyası (arama tablosuna sığmak için pek küçük)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"hasarlı biteÅŸlem indeks dosyası (yalancı birleÅŸtirme tablo üstbilgisine " +"sığmak için pek kısa)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"hasarlı biteÅŸlem indeks dosyası (yalancı birleÅŸtirme tablosuna sığmak için " +"pek kısa)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "hasarlı biteÅŸlem indeks dosyası, yalancı birleÅŸtirme tablosu pek kısa" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "biteÅŸlem indeksinde yinelenen girdi: '%s'" @@ -18274,6 +18570,10 @@ msgid "mismatch in bitmap results" msgstr "biteÅŸlem sonuçlarında uyuÅŸmazlık" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "yalancı birleÅŸtirme indeksi erim dışında (%<PRIu32> >= %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "öge bulunamadı: '%s'; '%s' paketinde, %<PRIuMAX> ofsetinde" @@ -18635,6 +18935,9 @@ msgstr "iÅŸ parçacıklarına ayrılmış 'lstat' oluÅŸturulamıyor: %s" msgid "unable to parse --pretty format" msgstr "--pretty biçimi ayrıştırılamıyor" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "gerekince getirme devre dışı; bazı nesneler kullanılamayabilir" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: getirme alt süreci çatallanamıyor" @@ -18658,6 +18961,67 @@ msgstr "object-info: argümanlardan sonra floÅŸ bekleniyordu" msgid "Removing duplicate objects" msgstr "YinelenmiÅŸ nesneler kaldırılıyor" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "%s için yalancı birleÅŸtirme düzenli ifadesi yüklenemedi: '%s'" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s negatif dışı bir deÄŸer olmalı, öntanımlı deÄŸer kullanılıyor" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s, 0 ve 1 arasında olmalıdır, öntanımlı kullanılıyor" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s pozitif olmalıdır, öntanımlı kullanılıyor" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "yalancı birleÅŸtirme grubu '%s' içinde gerekli dizgi yok" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "" +"yalancı birleÅŸtirme gribi '%s' içinde kararlıdan önce kararsız eÅŸik var" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"yapılandırmadaki yalancı birleÅŸtirme düzenli ifadesinde pek çok yakalama " +"grubu var (max=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"geniÅŸletilmiÅŸ yalancı birleÅŸtirme sınırlar dışında okundu (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"geniÅŸletilmiÅŸ yalancı birleÅŸtirme girdisi pek kısa (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "%s iÅŸlemesi için yalancı birleÅŸtirme bulunamadı, %<PRIuMAX> ofsetinde" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"geniÅŸletilmiÅŸ yalancı birleÅŸtirme araması sınırlar dışında (%<PRIu32> >= " +"%<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "sınırlar dışında okundu: (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "%s iÅŸlemesi için geniÅŸletilmiÅŸ yalancı birleÅŸtirme tablosu okunamadı" + msgid "could not start `log`" msgstr "'log' baÅŸlatılamadı" @@ -19084,6 +19448,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "beklenen biçim: %%(ahead-behind:<iÅŸlememsi>)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "beklenen biçim: %%(is-base:<iÅŸlememsi>)" + +#, c-format msgid "malformed field name: %.*s" msgstr "hatalı oluÅŸturulmuÅŸ alan adı: %.*s" @@ -19258,11 +19626,18 @@ msgstr "" msgid "log for %s is empty" msgstr "%s için olan günlük boÅŸ" +msgid "refusing to force and skip creation of reflog" +msgstr "baÅŸvuru günlüğünün oluÅŸturulma/atlanma zorlanması reddediliyor" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "hatalı ada iye '%s' baÅŸvurusunu güncelleme reddediliyor" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "'%s' yalancı baÅŸvurusunun güncellenmesi reddediliyor" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "'%s' baÅŸvurusu için update_ref baÅŸarısız oldu: %s" @@ -19293,6 +19668,32 @@ msgid "could not delete references: %s" msgstr "baÅŸvurular silinemedi: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "BaÅŸvuruların göç denemesi bitti, sonuç '%s' konumunda bulunabilir\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "geçici göç dizini '%s' kaldırılamadı" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "göç ettirilen baÅŸvurular '%s' konumunda bulunabilir" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"'%s' baÅŸvurusu kilitlenemiyor: '%s' hedefiyle bir sembolik baÅŸvuru " +"bekleniyordu; ancak bu normal bir baÅŸvuru" + +#, c-format +msgid "cannot open directory %s" +msgstr "%s dizini açılamıyor" + +msgid "Checking references consistency" +msgstr "BaÅŸvuruların tutarlılığı denetleniyor" + +#, c-format msgid "refname is dangerous: %s" msgstr "baÅŸvuru adı tehlikeli: %s" @@ -19324,8 +19725,8 @@ msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuruyu okurken hata" msgid "" "multiple updates for '%s' (including one via symref '%s') are not allowed" msgstr "" -"'%s' için birden çok güncellemeye ('%s' sembolik baÄŸlantısı ile olan bir " -"tanesini de içeren) izin verilmiyor" +"'%s' için birden çok güncellemeye ('%s' sembolik bağı ile olan bir tanesini " +"de içeren) izin verilmiyor" #, c-format msgid "cannot lock ref '%s': reference already exists" @@ -19357,7 +19758,7 @@ msgstr "baÅŸvuru adı %s bulunamadı" #, c-format msgid "refname %s is a symbolic ref, copying it is not supported" -msgstr "baÅŸvuru adı %s bir sembolik baÄŸlantı, onu kopyalamak desteklenmiyor" +msgstr "baÅŸvuru adı %s bir sembolik baÄŸ, onu kopyalamak desteklenmiyor" #, c-format msgid "invalid refspec '%s'" @@ -19923,12 +20324,15 @@ msgstr "yalnızca çıkış yapılacak dalın üstverisini indir" msgid "create repository within 'src' directory" msgstr "'src' dizininde depo oluÅŸtur" +msgid "specify if tags should be fetched during clone" +msgstr "etiketlerin klonlama sırasında getirilip getirilmeyeceÄŸini belirt" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <ana-dal>] [--full-clone]\n" -"\t[--[no-]src] <url> [<yazılma>]" +"\t[--[no-]src] [--[no-]tags] <url> [<listeleme>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -19947,6 +20351,10 @@ msgid "could not configure remote in '%s'" msgstr "'%s' içindeki uzak konum yapılandırılamadı" #, c-format +msgid "could not disable tags in '%s'" +msgstr "'%s' içindeki etiketler devre dışı bırakılamıyor" + +#, c-format msgid "could not configure '%s'" msgstr "'%s' yapılandırılamadı" @@ -20443,6 +20851,50 @@ msgstr "" "update-ref, tümüyle kalifiye bir baÅŸvuru adı gerektiriyor; örn. refs/heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' birleÅŸtirme iÅŸlemelerini kabul etmiyor" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick', bir birleÅŸtirme iÅŸlemesi almaz. BirleÅŸtirmeyi\n" +"yeniden oynatmak istediyseniz iÅŸlemede 'merge -C' kullanın." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword', bir birleÅŸtirme iÅŸlemesi almaz. BirleÅŸtirmeyi\n" +"yeniden oynatmak ve iÅŸleme iletisini düzenlemek istediyseniz\n" +"iÅŸlemede 'merge -c' kullanın." + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'edit', bir birleÅŸtirme iÅŸlemesi almaz. BirleÅŸtirmeyi\n" +"yeniden oynatmak istediyseniz iÅŸlemede 'merge -C' kullanın,sonrasında " +"denetimin size geri verilmesi için 'break'\n" +"yapın; böylece 'git commit --amend && git rebase --continue'\n" +"yapabilirsiniz." + +msgid "cannot squash merge commit into another commit" +msgstr "birleÅŸtirme iÅŸlemesi baÅŸka bir iÅŸlemeye tıkıştırılamaz" + +#, c-format msgid "invalid command '%.*s'" msgstr "geçersiz komut %.*s" @@ -20558,9 +21010,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "HEAD okunamıyor" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "'%s', '%s' konumuna kopyalanamıyor" +msgid "could not write commit message file" +msgstr "iÅŸleme iletisi dosyası yazılamadı" #, c-format msgid "" @@ -20958,6 +21409,22 @@ msgstr "cwd'ye geri dönülemiyor" msgid "failed to stat '%*s%s%s'" msgstr "'%*s%s%s' bilgileri alınamadı" +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' mutlak deÄŸil" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"'%s' konumundaki depoda belirsiz iyelik algılandı\n" +"%sBu dizin için istisna eklemek için ÅŸunu çağırın:\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Åžu anki çalışma dizini okunamıyor" @@ -20979,18 +21446,6 @@ msgstr "" "ayarlanmamış)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"'%s' konumundaki depoda belirsiz iyelik algılandı\n" -"%sBu dizin için istisna eklemek için ÅŸunu çağırın:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "çıplak depo '%s', kullanılamaz (safe.bareRepository '%s')" @@ -21294,6 +21749,15 @@ msgid "submodule git dir '%s' is inside git dir '%.*s'" msgstr "altmodül git dizini '%s', '%.*s' git dizini içinde" #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"'%.*s' ögesinin bir sembolik baÄŸ olması beklenmiyordu, '%s' altmodül yolunda" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "'%s' altmodül yolunun bir sembolik baÄŸ olması beklenmiyordu" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -21331,10 +21795,6 @@ msgstr "'%s', lstat yapılamadı" msgid "no remote configured to get bundle URIs from" msgstr "demet URI'lerini almak için bir uzak konum yapılandırılmamış" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "'%s' uzak konumunun yapılandırılmış bir URL'si yok" - msgid "could not get the bundle-uri list" msgstr "bundle-uri listesi alınamadı" @@ -21416,6 +21876,24 @@ msgstr "jeton" msgid "command token to send to the server" msgstr "sunucuya gönderilecek komut jetonu" +msgid "unit-test [<options>]" +msgstr "unit-test [<seçenekler>]" + +msgid "immediately exit upon the first failed test" +msgstr "ilk baÅŸarısız sınamada anında çık" + +msgid "suite[::test]" +msgstr "suite[::test]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "yalnızca sınama paketini veya bireysel <süit[::sınama]> çalıştır" + +msgid "suite" +msgstr "suite" + +msgid "exclude test suite <suite>" +msgstr "<süit> sınama süitini dışla" + #, c-format msgid "running trailer command '%s' failed" msgstr "'%s' artbilgi komutunu çalıştırma baÅŸarısız oldu" @@ -22582,6 +23060,9 @@ msgstr "'%s.final' yazılan e-postayı içeriyor.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases diÄŸer seçeneklerle uyumsuz\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases ve --translate-aliases birlikte kullanılamaz\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -22790,24 +23271,24 @@ msgid "Failed to send %s\n" msgstr "%s gönderilemedi\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "%s gönderilir gibi yapıldı\n" +msgid "Dry-Sent %s" +msgstr "%s gönderilir gibi yapıldı" #, perl-format -msgid "Sent %s\n" -msgstr "%s gönderildi\n" +msgid "Sent %s" +msgstr "%s gönderildi" -msgid "Dry-OK. Log says:\n" -msgstr "Sınama tamam. Günlük çıktısı:\n" +msgid "Dry-OK. Log says:" +msgstr "Sınama tamam. Günlük çıktısı:" -msgid "OK. Log says:\n" -msgstr "Tamam. Günlük çıktısı:\n" +msgid "OK. Log says:" +msgstr "Tamam. Günlük çıktısı:" msgid "Result: " msgstr "Sonuç: " -msgid "Result: OK\n" -msgstr "Sonuç: Tamam\n" +msgid "Result: OK" +msgstr "Sonuç: Tamam" #, perl-format msgid "can't open file %s" @@ -22880,4 +23361,4 @@ msgstr "%s, yedek sonek '%s' ile atlanıyor.\n" #. TRANSLATORS: please keep "[y|N]" as is. #, perl-format msgid "Do you really want to send %s? [y|N]: " -msgstr "%s ögesini gerçekten göndermek istiyor musunuz? [y|N]: " +msgstr "%s ögesini göndermeyi gerçekten istiyor musunuz? [y|N]: " @@ -6,10 +6,10 @@ # msgid "" msgstr "" -"Project-Id-Version: Git v2.45\n" +"Project-Id-Version: Git v2.46\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-27 09:55-0700\n" -"PO-Revision-Date: 2024-04-15 15:55-0700\n" +"POT-Creation-Date: 2023-04-11 09:55-0700\n" +"PO-Revision-Date: 2024-07-24 08:45-0700\n" "Last-Translator: Arkadii Yakovets <ark@cho.red>\n" "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n" "Language: uk\n" @@ -565,6 +565,10 @@ msgstr "" "p - показати поточний шматок\n" "? - показати довідку\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "ОчікувавÑÑ Ð»Ð¸ÑˆÐµ один Ñимвол, отримано \"%s\"" + msgid "No previous hunk" msgstr "Ðемає попереднього шматка" @@ -614,9 +618,19 @@ msgstr "Розщепити на %d шматків." msgid "Sorry, cannot edit this hunk" msgstr "Вибачайте, не можу редагувати цей шматок" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Ðевідома команда: \"%s\" (викориÑтовуйте \"?\" Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸)" + msgid "'git apply' failed" msgstr "\"git apply\" завершивÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾" +msgid "No changes." +msgstr "Ðічого не змінено." + +msgid "Only binary files changed." +msgstr "Змінено лише бінарні файли." + #, c-format msgid "" "\n" @@ -1487,6 +1501,9 @@ msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð´Ñ‚Ð¾ великого файлу gitattribu msgid "ignoring overly large gitattributes blob '%s'" msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð´Ñ‚Ð¾ великих gitattributes blob \"%s\"" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "неможливо викориÑтати --attr-source або GIT_ATTR_SOURCE без Ñховища" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "невірний --attr-source або GIT_ATTR_SOURCE" @@ -1809,13 +1826,6 @@ msgstr "неможливо виконати chmod %cx \"%s\"" msgid "Unstaged changes after refreshing the index:" msgstr "ÐеіндекÑовані зміни піÑÐ»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу:" -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"параметр add.interactive.useBuiltin було видалено!\n" -"ДивітьÑÑ Ð·Ð°Ð¿Ð¸Ñ Ñƒ \"git help config\" Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації." - msgid "could not read the index" msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ індекÑ" @@ -2258,6 +2268,9 @@ msgstr "перервати латаннÑ, але залишити HEAD на тРmsgid "show the patch being applied" msgstr "показати латку, що заÑтоÑовуєтьÑÑ" +msgid "try to apply current patch again" +msgstr "Ñпробувати заÑтоÑувати поточну латку ще раз" + msgid "record the empty patch as an empty commit" msgstr "запиÑати порожню латку Ñк порожній коміт" @@ -2314,9 +2327,6 @@ msgstr "git apply [<опції>] [<латка>...]" msgid "could not redirect output" msgstr "неможливо перенаправити вивід" -msgid "git archive: Remote with no URL" -msgstr "git archive: віддалене Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±ÐµÐ· URL" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: очікувалоÑÑŒ ACK/NAK, отримано flush-пакет" @@ -3231,6 +3241,9 @@ msgstr "Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÐ° потрібне Ñховище msgid "do not show bundle details" msgstr "не показувати деталі пакунка" +msgid "need a repository to verify a bundle" +msgstr "потрібне Ñховище Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ пакунка" + #, c-format msgid "%s is okay\n" msgstr "%s у порÑдку\n" @@ -4262,6 +4275,14 @@ 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\"" @@ -5095,15 +5116,50 @@ msgstr "" "новий файл індекÑу. ПереконайтеÑÑ, що диÑк не переповнений Ñ– квота\n" "не перевищена, а потім виконайте \"git restore --staged :/\" Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ." -msgid "git config [<options>]" -msgstr "git config [<опції>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<опціÑ-файлу>] [<опціÑ-відображеннÑ>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "нерозпізнаний аргумент --type, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<опціÑ-файлу>] [<опціÑ-відображеннÑ>] [--includes] [--all] " +"[--regexp=<регвир>] [--value=<значеннÑ>] [--fixed-value] [--" +"default=<Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ -за-умовчаннÑм>] <назва>" -msgid "only one type at a time" -msgstr "лише один тип за раз" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<опціÑ-файлу>] [--type=<тип>] [--all] [--value=<значеннÑ>] " +"[--fixed-value] <назва> <значеннÑ>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<опціÑ-файлу>] [--all] [--value=<значеннÑ>] [--fixed-" +"value] <назва> <значеннÑ>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<опціÑ-файлу>] <Ñтара-назва> <нова-назва>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<опціÑ-файлу>] <назва>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<опціÑ-файлу>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<опціÑ-файлу>] --get-colorbool <назва> [<stdout-is-tty>]" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<опціÑ-файлу>] [--type=<тип>] [--comment=<допиÑ>] [--all][--" +"value=<значеннÑ>] [--fixed-value] <назва> <значеннÑ>" msgid "Config file location" msgstr "Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ конфігурації" @@ -5129,55 +5185,6 @@ msgstr "blob-id" msgid "read config from given blob object" msgstr "прочитати конфігурацію з наданого blob-обʼєкту" -msgid "Action" -msgstr "ДіÑ" - -msgid "get value: name [value-pattern]" -msgstr "отримати значеннÑ: назва [шаблон-значеннÑ]" - -msgid "get all values: key [value-pattern]" -msgstr "отримати вÑÑ– значеннÑ: ключ [шаблон-значеннÑ]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "отримати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÐ³Ð²Ð¸Ñ€Ñƒ: регвир-назви [шаблон-значеннÑ]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "отримати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ñ— URL-адреÑи: розділ[.var] URL-адреÑа" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "замінити вÑÑ– відповідні змінні: назва Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ [шаблон-значеннÑ]" - -msgid "add a new variable: name value" -msgstr "додати нову змінну: назва значеннÑ" - -msgid "remove a variable: name [value-pattern]" -msgstr "видалити змінну: назва [шаблон-значеннÑ]" - -msgid "remove all matches: name [value-pattern]" -msgstr "видалити вÑÑ– збіги: назва [шаблон-значеннÑ]" - -msgid "rename section: old-name new-name" -msgstr "перейменувати розділ: Ñтара-назва нова-назва" - -msgid "remove a section: name" -msgstr "видалити розділ: назва" - -msgid "list all" -msgstr "показати вÑÑ– змінні" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "" -"викориÑтовувати рівніÑть Ñтрок при порівнÑнні значень з \"шаблон-значеннÑм\"" - -msgid "open an editor" -msgstr "відкрити редактор" - -msgid "find the color configured: slot [default]" -msgstr "знайти налаштований колір: Ñлот [за замовчуваннÑм]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "знайти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñƒ: slot [stdout-is-tty]" - msgid "Type" msgstr "Тип" @@ -5205,8 +5212,8 @@ msgstr "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÑˆÐ»ÑÑ… (файл або назва директорі msgid "value is an expiry date" msgstr "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ - дата Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії" -msgid "Other" -msgstr "Інше" +msgid "Display options" +msgstr "Опції відображеннÑ" msgid "terminate values with NUL byte" msgstr "завершити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð¼ NUL" @@ -5214,9 +5221,6 @@ msgstr "завершити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð¼ NUL" msgid "show variable names only" msgstr "показувати тільки назви змінних" -msgid "respect include directives on lookup" -msgstr "дотримуватиÑÑŒ директив Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸ пошуку" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "" "показати Ð¿Ð¾Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ— (файл, Ñтандартний ввід, blob, командний " @@ -5227,16 +5231,15 @@ msgstr "" "показати межі дії конфігурації (робоче дерево, локально, глобально, ÑиÑтема, " "команда)" -msgid "value" -msgstr "значеннÑ" +msgid "show config keys in addition to their values" +msgstr "показувати ключі конфігурації на додачу до їхніх значень" -msgid "with --get, use default value when missing entry" -msgstr "" -"з --get викориÑтовувати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм, Ñкщо Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñутній" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "нерозпізнаний аргумент --type, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "" -"зрозумілий Ð´Ð»Ñ Ð»ÑŽÐ´Ð¸Ð½Ð¸ Ñ€Ñдок ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ (# буде додано перед за потребою)" +msgid "only one type at a time" +msgstr "лише один тип за раз" #, c-format msgid "wrong number of arguments, should be %d" @@ -5314,46 +5317,75 @@ msgstr "" "ФÐЙЛ\"\n" "у \"git help worktree\" Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color Ñ– тип змінної не узгоджуютьÑÑ" +msgid "Other" +msgstr "Інше" -msgid "only one action at a time" -msgstr "лише одна Ð´Ñ–Ñ Ð·Ð° раз" +msgid "respect include directives on lookup" +msgstr "дотримуватиÑÑŒ директив Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸ пошуку" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --list або --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл конфігурації \"%s\"" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" +msgid "error processing config file(s)" +msgstr "помилка при обробці файлу(ів) конфігурації" + +msgid "Filter options" +msgstr "Опції фільтрації" + +msgid "return all values for multi-valued config options" +msgstr "повернути вÑÑ– Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð±Ð°Ð³Ð°Ñ‚Ð¾Ð·Ð½Ð°Ñ‡Ð½Ð¸Ñ… параметрів конфігурації" + +msgid "interpret the name as a regular expression" +msgstr "інтерпретувати назву Ñк регулÑрний вираз" + +msgid "show config with values matching the pattern" +msgstr "показати конфіг зі значеннÑми, що відповідають шаблону" + +msgid "use string equality when comparing values to value pattern" msgstr "" -"--show-origin заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --get, --get-all, --get-regexp та --list" +"викориÑтовувати Ñ€Ñдкову еквівалентніÑть при порівнÑнні з шаблоном значень" -msgid "--default is only applicable to --get" -msgstr "--default заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --get" +msgid "URL" +msgstr "URL" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до add/set/replace операцій" +msgid "show config matching the given URL" +msgstr "показати конфіг, що відповідає вказаній URL-адреÑÑ–" + +msgid "value" +msgstr "значеннÑ" + +msgid "use default value when missing entry" +msgstr "викориÑтовувати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм, Ñкщо Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñутній" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ з \"шаблоном-значеннÑ\"" -#, c-format -msgid "unable to read config file '%s'" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл конфігурації \"%s\"" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= не можна викориÑтовувати з --all або --url=" -msgid "error processing config file(s)" -msgstr "помилка при обробці файлу(ів) конфігурації" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= не можна викориÑтовувати з --all, --regexp або --value" -msgid "editing stdin is not supported" -msgstr "Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ stdin не підтримуєтьÑÑ" +msgid "Filter" +msgstr "ФільтраціÑ" -msgid "editing blobs is not supported" -msgstr "Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ blobs не підтримуєтьÑÑ" +msgid "replace multi-valued config option with new value" +msgstr "замінити багатозначний параметр конфігурації новим значеннÑм" -#, c-format -msgid "cannot create configuration file %s" -msgstr "неможливо Ñтворити конфігураційний файл %s" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"зрозумілий Ð´Ð»Ñ Ð»ÑŽÐ´Ð¸Ð½Ð¸ Ñ€Ñдок ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ (# буде додано попереду при " +"необхідноÑті)" + +msgid "add a new line without altering any existing values" +msgstr "додати новий Ñ€Ñдок, не змінюючи жодного з Ñ–Ñнуючих значень" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ з --value=<шаблон>" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append не можна викориÑтовувати з --value=<шаблон>" #, c-format msgid "" @@ -5367,6 +5399,87 @@ msgstr "" msgid "no such section: %s" msgstr "немає такого розділу: %s" +msgid "editing stdin is not supported" +msgstr "Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ stdin не підтримуєтьÑÑ" + +msgid "editing blobs is not supported" +msgstr "Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ blobs не підтримуєтьÑÑ" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "неможливо Ñтворити конфігураційний файл %s" + +msgid "Action" +msgstr "ДіÑ" + +msgid "get value: name [<value-pattern>]" +msgstr "отримати значеннÑ: назва [шаблон-значеннÑ]" + +msgid "get all values: key [<value-pattern>]" +msgstr "отримати вÑÑ– значеннÑ: ключ [шаблон-значеннÑ]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "отримати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÐ³Ð²Ð¸Ñ€Ñƒ: регвир-назви [шаблон-значеннÑ]" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "" +"отримати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ñ— URL-адреÑи: розділ[.змінна] URL-адреÑа" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "замінити вÑÑ– відповідні змінні: назва Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ [шаблон-значеннÑ]" + +msgid "add a new variable: name value" +msgstr "додати нову змінну: назва значеннÑ" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "видалити змінну: назва [шаблон-значеннÑ]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "видалити вÑÑ– збіги: назва [шаблон-значеннÑ]" + +msgid "rename section: old-name new-name" +msgstr "перейменувати розділ: Ñтара-назва нова-назва" + +msgid "remove a section: name" +msgstr "видалити розділ: назва" + +msgid "list all" +msgstr "показати вÑÑ– змінні" + +msgid "open an editor" +msgstr "відкрити редактор" + +msgid "find the color configured: slot [<default>]" +msgstr "знайти налаштований колір: Ñлот [<за замовчуваннÑм>]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "знайти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñƒ: Ñлот [<stdout-is-tty>]" + +msgid "with --get, use default value when missing entry" +msgstr "" +"з --get викориÑтовувати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм, Ñкщо Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñутній" + +msgid "--get-color and variable type are incoherent" +msgstr "--get-color Ñ– тип змінної не узгоджуютьÑÑ" + +msgid "no action specified" +msgstr "дію не зазначено" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --list або --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --get, --get-all, --get-regexp та --list" + +msgid "--default is only applicable to --get" +msgstr "--default заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --get" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до add/set/replace операцій" + msgid "print sizes in human readable format" msgstr "показувати розмір у зручному Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ñ–" @@ -6200,6 +6313,10 @@ msgstr "конфіг" msgid "config key storing a list of repository paths" msgstr "ключ конфігурації, в Ñкому зберігаєтьÑÑ ÑпиÑок шлÑхів до Ñховищ" +msgid "keep going even if command fails in a repository" +msgstr "" +"продовжувати роботу, навіть Ñкщо команда завершилаÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾ в репозиторії" + msgid "missing --config=<config>" msgstr "відÑутній --config=<конфіг>" @@ -7666,8 +7783,11 @@ msgstr "позначити Ñ€Ñд Ñк N-не перекиданнÑ" msgid "max length of output filename" msgstr "макÑимальна довжина назви вихідного файлу" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "викориÑтати [RFC PATCH] заміÑть [PATCH]" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "додати <rfc> (за замовчуваннÑм \"RFC\") перед \"PATCH\"" msgid "cover-from-description-mode" msgstr "cover-from-description-mode" @@ -7937,11 +8057,12 @@ msgstr "" "deduplicate, --eol" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<виконавчий-файл>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<виконавчий-" +"файл>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<ключ>]\n" " [--symref] [<Ñховище> [<шаблони>...]]" @@ -7957,8 +8078,11 @@ msgstr "шлÑÑ… до git-upload-pack на віддаленому Ñервері msgid "limit to tags" msgstr "обмежити до тегів" -msgid "limit to heads" -msgstr "обмежити до голів" +msgid "limit to branches" +msgstr "обмежити до гілок" + +msgid "deprecated synonym for --branches" +msgstr "заÑтарілий Ñинонім до --branches" msgid "do not show peeled tags" msgstr "не показувати очищені теги" @@ -10619,6 +10743,22 @@ 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 "specify the reference format to convert to" +msgstr "вкажіть формат поÑиланнÑ, в Ñкий потрібно конвертувати" + +msgid "perform a non-destructive dry-run" +msgstr "виконати неруйнівний пробний запуÑк" + +msgid "missing --ref-format=<format>" +msgstr "відÑутній --ref-format=<формат>" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "Ñховище вже викориÑтовує формат \"%s\"" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -10907,9 +11047,6 @@ msgstr "* віддалене %s" msgid " Fetch URL: %s" msgstr " URL-адреÑа отриманнÑ: %s" -msgid "(no URL)" -msgstr "(без URL-адреÑи)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -10918,6 +11055,9 @@ msgstr "(без URL-адреÑи)" msgid " Push URL: %s" msgstr " URL-адреÑа надÑиланнÑ: %s" +msgid "(no URL)" +msgstr "(без URL-адреÑи)" + #, c-format msgid " HEAD branch: %s" msgstr " HEAD гілка: %s" @@ -11030,10 +11170,6 @@ msgstr "запитувати URL-адреÑи надÑилань заміÑть msgid "return all URLs" msgstr "повернути вÑÑ– URL-адреÑи" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "не налаштовано URL-адреÑи Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ \"%s\"" - msgid "manipulate push URLs" msgstr "маніпулювати URL-адреÑами надÑиланнÑ" @@ -11402,7 +11538,7 @@ msgid "only one pattern can be given with -l" msgstr "тільки один шаблон може бути заданий з -l" msgid "need some commits to replay" -msgstr "потрібні деÑкі комміти Ð´Ð»Ñ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ" +msgstr "потрібні деÑкі коміти Ð´Ð»Ñ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ" msgid "--onto and --advance are incompatible" msgstr "--onto та --advance неÑуміÑні" @@ -11468,7 +11604,7 @@ msgid "replaying down to root commit is not supported yet!" msgstr "Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð´Ð¾ кореневого коміту поки що не підтримуєтьÑÑ!" msgid "replaying merge commits is not supported yet!" -msgstr "Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ð¼Ñ–Ñ‚Ñ–Ð² Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ð¾ÐºÐ¸ що не підтримуєтьÑÑ!" +msgstr "Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð² Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ð¾ÐºÐ¸ що не підтримуєтьÑÑ!" msgid "" "git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]" @@ -12047,12 +12183,12 @@ msgstr "Ðевідомий хеш-алгоритм" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<н>]] [--abbrev[=<н>]] [--tags]\n" -" [--heads] [--] [<шаблон>...]" +" [-s | --hash[=<н>]] [--abbrev[=<н>]] [--branches] [--tags]\n" +" [--] [<шаблон>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -12075,11 +12211,11 @@ msgstr "поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує" msgid "failed to look up reference" msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ поÑиланнÑ" -msgid "only show tags (can be combined with heads)" -msgstr "показати тільки теги (можна комбінувати з верхівками)" +msgid "only show tags (can be combined with branches)" +msgstr "показати тільки теги (можна комбінувати з гілками)" -msgid "only show heads (can be combined with tags)" -msgstr "показати тільки верхівки (можна комбінувати з тегами)" +msgid "only show branches (can be combined with tags)" +msgstr "показати тільки гілки (можна комбінувати з тегами)" msgid "check for reference existence without resolving" msgstr "перевірÑти наÑвніÑть поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð±ÐµÐ· розвʼÑзаннÑ" @@ -12714,14 +12850,14 @@ msgstr "" "відмовлено в Ñтворенні/викориÑтанні \"%s\" у git директорії іншого підмодулÑ" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "не вдалоÑÑ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ñ‚Ð¸ \"%s\" у шлÑÑ… Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ \"%s\"" - -#, c-format msgid "directory not empty: '%s'" msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð½Ðµ порожнÑ: \"%s\"" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "не вдалоÑÑ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ñ‚Ð¸ \"%s\" у шлÑÑ… Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ \"%s\"" + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ директорію Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð´Ð»Ñ \"%s\"" @@ -13086,14 +13222,16 @@ msgstr "причина оновленнÑ" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <ідентифікатор-ключа>] [-f] [-m <допиÑ> | -F <файл>] [-" "e]\n" +" [(--trailer <токен>[(=|:)<значеннÑ>])...]\n" " <назва-тегу> [<коміт> | <об’єкт>]" msgid "git tag -d <tagname>..." -msgstr "git tag -d <назва-тега>..." +msgstr "git tag -d <назва-тегу>..." msgid "" "git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n" @@ -13948,9 +14086,6 @@ msgstr "нерозпізнаний заголовок: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "У Ñховищі не виÑтачає обовʼÑзкових комітів:" -msgid "need a repository to verify a bundle" -msgstr "потрібне Ñховище Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ пакунка" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14353,6 +14488,9 @@ msgstr "Отримати те, що надÑилаєтьÑÑ Ð´Ð¾ Ñховища msgid "Manage reflog information" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ”ÑŽ журналу поÑилань" +msgid "Low-level access to refs" +msgstr "Ðизькорівневий доÑтуп до поÑилань" + msgid "Manage set of tracked repositories" msgstr "Керувати набором відÑтежуваних Ñховищ" @@ -14364,8 +14502,8 @@ msgstr "Створити, показати, видалити поÑÐ¸Ð»Ð°Ð½Ð½Ñ msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too" msgstr "" -"ЕКСПЕРИМЕÐТÐЛЬÐО: Ð’Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ð¼Ñ–Ñ‚Ñ–Ð² на новій базі також працює з " -"порожніми Ñховищами" +"ЕКСПЕРИМЕÐТÐЛЬÐО: Ð’Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð² на новій базі також працює з порожніми " +"Ñховищами" msgid "Generates a summary of pending changes" msgstr "Створює підÑумок змін Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð»Ñду" @@ -14440,7 +14578,7 @@ msgid "Initialize, update or inspect submodules" msgstr "Ініціалізувати, оновити або перевірити підмодулі" msgid "Bidirectional operation between a Subversion repository and Git" -msgstr "Двонаправлена Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð¼Ñ–Ð¶ Subversion Ñховищем та Git" +msgstr "ДвонапрÑмлена Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð¼Ñ–Ð¶ Subversion Ñховищем та Git" msgid "Switch branches" msgstr "Переключити гілки" @@ -14656,6 +14794,14 @@ msgstr "необхідний шматок OID lookup коміт-графа віРmsgid "commit-graph required commit data chunk missing or corrupted" msgstr "необхідний шматок commit data коміт-графа відÑутній або пошкоджений" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ñ–Ð² Блума Ð´Ð»Ñ ÑˆÐ°Ñ€Ñƒ коміт-графа \"%s\" через неÑуміÑніÑть " +"параметрів" + msgid "commit-graph has no base graphs chunk" msgstr "коміт-граф не має шматка базових графів" @@ -14780,6 +14926,14 @@ msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ð¼Ñ–Ñ‚-графа" msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "Ñпроба запиÑати коміт-граф, але \"core.commitGraph\" відключено" +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"Ñпроба запиÑати коміт-граф, але \"commitGraph.changedPathsVersion\" (%d) не " +"підтримуєтьÑÑ" + msgid "too many commits to write graph" msgstr "занадто багато комітів, щоб запиÑати граф" @@ -16635,17 +16789,21 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <шлÑÑ…>] [-c <назва>=<значеннÑ>]\n" " [--exec-path[=<шлÑÑ…>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<шлÑÑ…>] [--work-tree=<шлÑÑ…>] [--namespace=<назва>]\n" -"[--config-env=<назва>=<змінна-оточеннÑ>] <команда> [<аргументи>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<шлÑÑ…>]\n" +" [--work-tree=<шлÑÑ…>] [--namespace=<назва>] [--config-" +"env=<шлÑÑ…>=<змінна-оточеннÑ>]\n" +" <команда> [<аргументи>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -16988,13 +17146,13 @@ msgstr "" "Ви можете вимкнути це Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð·Ð° допомогою \"git config advice." "ignoredHook false\"." +msgid "not a git repository" +msgstr "не Ñ” git Ñховищем" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "аргумент до --packfile має бути коректним хешем (отримано \"%s\")" -msgid "not a git repository" -msgstr "не Ñ” git Ñховищем" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "" @@ -17006,6 +17164,9 @@ msgstr "Контроль Ð´ÐµÐ»ÐµÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ підтримуєтьÑÑ msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "Ð—Ð°ÐºÑ€Ñ–Ð¿Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸Ñ… ключів не підтримуєтьÑÑ Ð· cURL < 7.39.0" +msgid "Unknown value for http.proactiveauth" +msgstr "Ðевідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ http.proactiveauth" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE не підтримуєтьÑÑ Ð· cURL < 7.44.0" @@ -17023,6 +17184,12 @@ msgstr "" msgid "Could not set SSL backend to '%s': already set" msgstr "Ðе вдалоÑÑ Ð²Ñтановити SSL обробник в \"%s\": вже вÑтановлено" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "відмова від Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ cookies з http.cookiefile \"-\"" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ http.savecookies Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½ÑŒÐ¾Ð³Ð¾ http.cookiefile" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -17198,8 +17365,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (відÑутні коміти)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "помилка: не вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17226,12 +17393,13 @@ msgstr "" "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s, але Ñ–Ñнує кілька можливих варіантів злиттÑ:\n" "%s" -msgid "failed to execute internal merge" -msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ внутрішнє злиттÑ" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "помилка: не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ внутрішнє Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ %s" #, c-format -msgid "unable to add %s to database" -msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %s до бази даних" +msgid "error: unable to add %s to database" +msgstr "помилка: не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %s до бази даних" #, c-format msgid "Auto-merging %s" @@ -17328,12 +17496,12 @@ msgstr "" "в %s." #, c-format -msgid "cannot read object %s" -msgstr "неможливо прочитати обʼєкт %s" +msgid "error: cannot read object %s" +msgstr "помилка: неможливо прочитати обʼєкт %s" #, c-format -msgid "object %s is not a blob" -msgstr "обʼєкт %s не Ñ” blob" +msgid "error: object %s is not a blob" +msgstr "помилка: обʼєкт %s не Ñ” blob" #, c-format msgid "" @@ -17470,6 +17638,10 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "не знаю, що робити з %06o %s \"%s\"" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ %s вперед до наÑтупного коміту:" @@ -17508,6 +17680,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (знайдено більше одного злиттÑ)" +msgid "failed to execute internal merge" +msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ внутрішнє злиттÑ" + +#, c-format +msgid "unable to add %s to database" +msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %s до бази даних" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -17610,6 +17789,14 @@ msgstr "" "КОÐФЛІКТ (перейменовано/перейменовано): перейменовано директорію %s->%s в " "%s. Перейменовано директорію %s->%s в %s" +#, c-format +msgid "cannot read object %s" +msgstr "неможливо прочитати обʼєкт %s" + +#, c-format +msgid "object %s is not a blob" +msgstr "обʼєкт %s не Ñ” blob" + msgid "modify" msgstr "змінити" @@ -17693,10 +17880,6 @@ msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ Ñ€Ñдок: %s" msgid "malformed line: %s" msgstr "невірно Ñформований Ñ€Ñдок: %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑть контрольних Ñум" - msgid "could not load pack" msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок" @@ -17704,6 +17887,10 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок" msgid "could not open index for %s" msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ %s" +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑть контрольних Ñум" + msgid "Adding packfiles to multi-pack-index" msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index" @@ -18317,6 +18504,17 @@ msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ обʼєкт: %s" msgid "hash mismatch %s" msgstr "невідповідніÑть хешу %s" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "дубльований елемент під Ñ‡Ð°Ñ Ð·Ð°Ð¿Ð¸Ñу bitmap індекÑу: \"%s\"" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "Ñпроба зберегти невибраний коміт: \"%s\"" + +msgid "too many pseudo-merges" +msgstr "занадто багато пÑевдозлиттÑ" + msgid "trying to write commit not in index" msgstr "Ñпроба запиÑати коміт, Ñкого немає в індекÑÑ–" @@ -18339,8 +18537,21 @@ msgstr "" msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "" +"пошкоджений файл bitmap індекÑу (занадто малий, щоб вміÑтити таблицю пошуку)" + +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"пошкоджений файл bitmap індекÑу (занадто малий, щоб вміÑтити заголовок " +"таблиці пÑевдозлиттÑ" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" "пошкоджений файл bitmap індекÑу (занадто короткий, щоб вміÑтити таблицю " -"пошуку)" +"пÑевдозлиттÑ)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "пошкоджений файл bitmap індекÑу, Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿ÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ мала" #, c-format msgid "duplicate entry in bitmap index: '%s'" @@ -18437,6 +18648,10 @@ msgid "mismatch in bitmap results" msgstr "розбіжніÑть в bitmap результатах" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "Ñ–Ð½Ð´ÐµÐºÑ Ð¿ÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ð¾Ð·Ð° діапазоном (%<PRIu32> >= %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ \"%s\" у пакунку \"%s\" зі зміщеннÑм %<PRIuMAX>" @@ -18808,6 +19023,9 @@ msgstr "не вдалоÑÑ Ñтворити потоковий lstat: %s" msgid "unable to parse --pretty format" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ --pretty формат" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "лінива вибірка вимкнена; деÑкі обʼєкти можуть бути недоÑтупні" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: не вдалоÑÑ Ñ€Ð¾Ð·Ð³Ð°Ð»ÑƒÐ¶Ð¸Ñ‚Ð¸ Ð¿Ñ–Ð´Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ" @@ -18831,6 +19049,65 @@ msgstr "object-info: очікувавÑÑ flush піÑÐ»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ñ–Ð²" msgid "Removing duplicate objects" msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´ÑƒÐ±Ð»Ñ–ÐºÐ°Ñ‚Ñ–Ð² обʼєктів" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ регвир пÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ %s: \"%s\"" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "" +"%s має бути невідʼємним значеннÑм, викориÑтано Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "" +"%s має бути в діапазоні від 0 до 1, викориÑтано Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s має бути додатнім, викориÑтано Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "у групі пÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ \"%s\" відÑутній потрібний шаблон" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "група пÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ \"%s\" має неÑтабільний поріг перед Ñтабільним" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"регвир пÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· конфігурації має забагато груп Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ " +"(max=%<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ð° межами (%<PRIuMAX> >= %<PRIuMAX>) при розширеному пÑевдозлитті" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"Ð·Ð°Ð¿Ð¸Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ð¾Ð³Ð¾ пÑÐµÐ²Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ малий (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ пÑÐµÐ²Ð¾Ð´Ð¾Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ð° %s зі зміщеннÑм %<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "розширене пÑевдозлиттÑ, пошук за межами (%<PRIu32> >= %<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ð° межами: (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ таблицю розширеного пÑевдо-Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ %s" + msgid "could not start `log`" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ \"log\"" @@ -19434,11 +19711,18 @@ msgstr "лог Ð´Ð»Ñ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ %s неÑподівано завершРmsgid "log for %s is empty" msgstr "лог Ð´Ð»Ñ %s порожній" +msgid "refusing to force and skip creation of reflog" +msgstr "відмовлено в примуÑовому пропуÑку ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€ÐµÑ„Ð»Ð¾Ð³Ñƒ" + #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "відмовлено в оновленні поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· невірною назвою \"%s\"" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "відмовлено в оновленні пÑевдопоÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "update_ref завершивÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾ Ð´Ð»Ñ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": %s" @@ -19469,6 +19753,25 @@ msgid "could not delete references: %s" msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ поÑиланнÑ: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "Закінчено пробну міграцію поÑилань, результат можна знайти в \"%s\"\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ тимчаÑову директорію міграції \"%s\"" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "перенеÑені поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° знайти в \"%s\"" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"неможливо заблокувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": очікувалоÑÑŒ Ñимвольне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· " +"призначеннÑм \"%s\", але це звичайне поÑиланнÑ" + +#, c-format msgid "refname is dangerous: %s" msgstr "refname Ñ” небезпечним: %s" @@ -20446,7 +20749,7 @@ msgid "" " git rebase --continue\n" msgstr "" "ви маєте індекÑовані зміни у вашому робочому дереві\n" -"Якщо ці зміни мають бути ÑтиÑнуті у попередній коміт, запуÑтіть:\n" +"Якщо ці зміни мають бути зчавлені у попередній коміт, запуÑтіть:\n" "\n" " git commit --amend %s\n" "\n" @@ -20657,6 +20960,49 @@ msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s" msgstr "update-ref потребує повної назви поÑиланнÑ, наприклад, refs/heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "\"%s\" не приймає коміти злиттÑ" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"\"pick\" не приймає коміти злиттÑ. Якщо ви хочете\n" +"відтворити злиттÑ, викориÑтовуйте \"merge -C\" Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ð°." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"\"reword\" не приймає коміти злиттÑ. Якщо ви хочете\n" +"відтворити Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° змінити текÑÑ‚ допиÑу, викориÑтовуйте\n" +"\"merge -c\" Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ð°." + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"\"edit\" не приймає коміти злиттÑ. Якщо ви хочете\n" +"відтворити злиттÑ, викориÑтовуйте \"merge -C\" Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ð°, а потім\n" +"\"break\" Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ, щоб ви могли\n" +"виконати \"git commit --amend && git rebase --continue\"." + +msgid "cannot squash merge commit into another commit" +msgstr "неможливо зчавити коміт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð² інший коміт" + +#, c-format msgid "invalid command '%.*s'" msgstr "неприпуÑтима команда \"%.*s\"" @@ -20774,9 +21120,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "неможливо прочитати HEAD" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "не вдалоÑÑ Ñкопіювати \"%s\" в \"%s\"" +msgid "could not write commit message file" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл допиÑу до коміта" #, c-format msgid "" @@ -21180,6 +21525,18 @@ msgstr "неможливо повернутиÑÑ Ð´Ð¾ поточної робо msgid "failed to stat '%*s%s%s'" msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати \"%*s%s%s\"" +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"виÑвлено Ñумнівне право влаÑноÑті у Ñховищі за адреÑою \"%s\"\n" +"%sЩоб додати винÑток Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— директорії, виконайте:\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ поточну робочу директорію" @@ -21202,18 +21559,6 @@ msgstr "" "вÑтановлено)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"виÑвлено Ñумнівне право влаÑноÑті у Ñховищі за адреÑою \"%s\"\n" -"%sЩоб додати винÑток Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— директорії, виконайте:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "" "неможливо викориÑтати порожнє Ñховище \"%s\" (safe.bareRepository " @@ -21518,7 +21863,17 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ підмодуль \"%s\"." #, c-format msgid "submodule git dir '%s' is inside git dir '%.*s'" -msgstr "підмодуль git dir \"%s\" знаходитьÑÑ Ð²Ñередині git директорії \"%.*s\"" +msgstr "підмодуль git dir \"%s\" знаходитьÑÑ Ð²Ñередині git директорії \"%*s\"" + +#, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"очікувалоÑÑŒ, що \"%.*s\" у шлÑху Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ \"%s\" не буде Ñимвольним " +"поÑиланнÑм" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "очікувалоÑÑŒ, що шлÑÑ… Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ \"%s\" не буде Ñимвольним поÑиланнÑм" #, c-format msgid "" @@ -21561,10 +21916,6 @@ msgstr "" "немає налаштованого віддаленого Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ URI пакунків з " "нього" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "віддалений \"%s\" не має налаштованої URL-адреÑи" - msgid "could not get the bundle-uri list" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ÑпиÑок bundle-uri" @@ -23058,24 +23409,24 @@ msgid "Failed to send %s\n" msgstr "Ðе вдалоÑÑ Ð½Ð°Ð´Ñ–Ñлати %s\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Пробно відправлено %s\n" +msgid "Dry-Sent %s" +msgstr "Пробно відправлено %s" #, perl-format -msgid "Sent %s\n" -msgstr "Відправлено %s\n" +msgid "Sent %s" +msgstr "Відправлено %s" -msgid "Dry-OK. Log says:\n" -msgstr "Пробно OK. Журнал каже:\n" +msgid "Dry-OK. Log says:" +msgstr "Пробно OK. Журнал каже:" -msgid "OK. Log says:\n" -msgstr "ОК. Журнал каже:\n" +msgid "OK. Log says:" +msgstr "ОК. Журнал каже:" msgid "Result: " msgstr "Результат: " -msgid "Result: OK\n" -msgstr "Результат: OK\n" +msgid "Result: OK" +msgstr "Результат: OK" #, perl-format msgid "can't open file %s" @@ -2,19 +2,72 @@ # Bản dịch tiếng Việt dà nh cho GIT-CORE. # This file is distributed under the same license as the git-core package. # https://raw.githubusercontent.com/git-l10n/git-po/pot/main/po/git.pot +# --- # Copyright (C) 2012-2022, Translation Project, Vietnamese Team <http://translationproject.org/team/vi.html> # Copyright (C) 2024, VÅ© Tiến Hưng <newcomerminecraft@gmail.com> # Nguyá»…n Thái Ngá»c Duy <pclouds@gmail.com>, 2012. # Äoà n Trần Công Danh <congdanhqx@gmail.com>, 2020. # Trần Ngá»c Quân <vnwildman@gmail.com>, 2012-2022. # VÅ© Tiến Hưng <newcomerminecraft@gmail.com>, 2024. +# --- +# BẢNG THUẬT NGá»® / TERMINOLOGY +# Updated: 2024-07-26, git 2.46 # -msgid "" -msgstr "" -"Project-Id-Version: git 2.45\n" +# Ghi chú: +# - Bảng thuáºt ngữ nà y chưa hoà n thiện. +# - Tuỳ và o ngữ cảnh, bản dịch có thể thay đổi cho phù hợp. +# +# CÃCH VIẾT TẮT +# n. = danh từ +# v. = động từ +# a. = tÃnh từ +# +# +------------------------------------------------------------------+ +# | Thuáºt ngữ / Term | Bản dịch / Translation | +# +------------------------------------------------------------------+ +# | file | táºp tin | +# | folder | thư mục | +# | path | đưá»ng dẫn | +# | error | lá»—i | +# | fatal / fatal error | lá»—i nghiêm trá»ng | +# | warning | cảnh báo | +# | (v.) commit | chuyển giao | +# | (n.) commit | lần chuyển giao | +# | (n.) branch | nhánh | +# | (v.) branch | tạo nhánh | +# | (n.) log | nháºt ký | +# | (v.) log | ghi lại | +# | (n.) ref/refs | tham chiếu | +# | hunk | khúc | +# | index | chỉ mục | +# | (n.) stage | vùng chá» | +# | (v.) stage <...> | đưa <...> và o vùng chá» | +# | (v.) unstage <...> | bá» <...> ra khá»i vùng chá» | +# | revert | hoà n nguyên | +# | add | thêm | +# | restore | phục hồi | +# | (n./v.) change | thay đổi | +# | (v.) update | cáºp nháºt | +# | (v.) track | theo dõi | +# | (v.) untrack | bá» theo dõi | +# | (a.) tracked | được theo dõi | +# | (a.) untracked | không được theo dõi | +# | (v.) parse | hiểu cú pháp | +# | (n.) output | đầu ra, kết quả | +# | (v.) output | in ra, xuất ra | +# | (v.) merge | hoà trá»™n | +# | (v.) rebase | cải tổ | +# | (v.) squash | squash | +# | (v.) amend | tu bổ | +# | | | +# | ... TODO ... | | +# +------------------------------------------------------------------+ +msgid "" +msgstr "" +"Project-Id-Version: git 2.47\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-25 18:57+0000\n" -"PO-Revision-Date: 2024-04-28 14:01+0700\n" +"POT-Creation-Date: 2024-10-05 01:20+0000\n" +"PO-Revision-Date: 2024-10-05 16:48+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" @@ -44,7 +97,7 @@ msgstr "Cáºp nháºt" #, c-format msgid "could not stage '%s'" -msgstr "không thể đưa '%s' lên bệ phóng" +msgstr "không thể đưa '%s' và o vùng chá»" msgid "could not write index" msgstr "không thể ghi chỉ mục" @@ -113,7 +166,7 @@ msgstr "" msgid "revert staged set of changes back to the HEAD version" msgstr "" -"hoà n nguyên lại táºp hợp các thay đổi đã được đưa lên bệ phóng trở lại phiên " +"hoà n nguyên lại táºp hợp các thay đổi đã được đưa và o vùng chá» trở lại phiên " "bản HEAD" msgid "pick hunks and update selectively" @@ -125,7 +178,7 @@ msgstr "xem khác biệt giữa HEAD và chỉ mục" msgid "add contents of untracked files to the staged set of changes" msgstr "" "thêm ná»™i dung cá»§a các táºp tin chưa được theo dõi và o táºp hợp các thay đổi đã " -"được đưa lên bệ phóng" +"được đưa và o vùng chá»" msgid "Prompt help:" msgstr "Trợ giúp vá» nhắc:" @@ -164,10 +217,10 @@ msgid "What now" msgstr "Giá» thì sao" msgid "staged" -msgstr "đã đưa lên bệ phóng" +msgstr "đã đưa và o vùng chá»" msgid "unstaged" -msgstr "chưa đưa lên bệ phóng" +msgstr "chưa đưa và o vùng chá»" msgid "path" msgstr "đưá»ng-dẫn" @@ -181,26 +234,26 @@ msgstr "Tạm biệt.\n" #, c-format msgid "Stage mode change [y,n,q,a,d%s,?]? " -msgstr "ÄÆ°a lên bệ phóng thay đổi chế độ [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a và o vùng chá» thay đổi chế độ [y,n,q,a,d%s,?]? " #, c-format msgid "Stage deletion [y,n,q,a,d%s,?]? " -msgstr "ÄÆ°a lên bệ phóng thao tác xoá [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a và o vùng chá» thao tác xoá [y,n,q,a,d%s,?]? " #, c-format msgid "Stage addition [y,n,q,a,d%s,?]? " -msgstr "ÄÆ°a lên bệ phóng thao tác thêm [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a và o vùng chá» thao tác thêm [y,n,q,a,d%s,?]? " #, c-format msgid "Stage this hunk [y,n,q,a,d%s,?]? " -msgstr "ÄÆ°a lên bệ phóng khúc nà y [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a và o vùng chá» khúc nà y [y,n,q,a,d%s,?]? " msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "staging." msgstr "" "Nếu bản vá được áp dụng hoà n toà n, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " -"để chuyển lên bệ phóng." +"để chuyển và o vùng chá»." msgid "" "y - stage this hunk\n" @@ -209,11 +262,11 @@ msgid "" "a - stage this hunk and all later hunks in the file\n" "d - do not stage this hunk or any of the later hunks in the file\n" msgstr "" -"y - đưa lên bệ phóng khúc nà y\n" -"n - đừng đưa lên bệ phóng khúc nà y\n" -"q - thoát; đừng đưa lên bệ phóng khúc nà y hay bất kỳ cái nà o còn lại\n" -"a - đưa lên bệ phóng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng đưa lên bệ phóng khúc nà y hay bất kỳ cái nà o còn lại trong táºp tin\n" +"y - đưa và o vùng chá» khúc nà y\n" +"n - đừng đưa và o vùng chá» khúc nà y\n" +"q - thoát; đừng đưa và o vùng chá» khúc nà y hay bất kỳ cái nà o còn lại\n" +"a - đưa và o vùng chá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" +"d - đừng đưa và o vùng chá» khúc nà y hay bất kỳ cái nà o còn lại trong táºp tin\n" #, c-format msgid "Stash mode change [y,n,q,a,d%s,?]? " @@ -253,26 +306,26 @@ msgstr "" #, c-format msgid "Unstage mode change [y,n,q,a,d%s,?]? " -msgstr "Bá» ra khá»i bệ phóng thay đổi chế độ [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i vùng chá» thay đổi chế độ [y,n,q,a,d%s,?]? " #, c-format msgid "Unstage deletion [y,n,q,a,d%s,?]? " -msgstr "Bá» ra khá»i bệ phóng thao tác xoá [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i vùng chá» thao tác xoá [y,n,q,a,d%s,?]? " #, c-format msgid "Unstage addition [y,n,q,a,d%s,?]? " -msgstr "Bá» ra khá»i bệ phóng thao tác thêm [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i vùng chá» thao tác thêm [y,n,q,a,d%s,?]? " #, c-format msgid "Unstage this hunk [y,n,q,a,d%s,?]? " -msgstr "Bá» ra khá»i bệ phóng khúc nà y [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i vùng chá» khúc nà y [y,n,q,a,d%s,?]? " msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "unstaging." msgstr "" "Nếu bản vá được áp dụng hoà n toà n, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " -"để bá» ra khá»i bệ phóng." +"để bá» ra khá»i vùng chá»." msgid "" "y - unstage this hunk\n" @@ -281,11 +334,11 @@ msgid "" "a - unstage this hunk and all later hunks in the file\n" "d - do not unstage this hunk or any of the later hunks in the file\n" msgstr "" -"y - đưa ra khá»i bệ phóng khúc nà y\n" -"n - đừng đưa ra khá»i bệ phóng khúc nà y\n" -"q - thoát; đừng đưa ra khá»i bệ phóng khúc nà y hay bất kỳ cái nà o còn lại\n" -"a - đưa ra khá»i bệ phóng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng đưa ra khá»i bệ phóng khúc nà y hay bất kỳ cái nà o còn lại trong táºp " +"y - đưa ra khá»i vùng chá» khúc nà y\n" +"n - đừng đưa ra khá»i vùng chá» khúc nà y\n" +"q - thoát; đừng đưa ra khá»i vùng chá» khúc nà y hay bất kỳ cái nà o còn lại\n" +"a - đưa ra khá»i vùng chá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" +"d - đừng đưa ra khá»i vùng chá» khúc nà y hay bất kỳ cái nà o còn lại trong táºp " "tin\n" #, c-format @@ -552,7 +605,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - để lại khúc nà y là chưa quyết định, xem khúc chưa quyết định kế tiếp\n" @@ -563,9 +616,13 @@ msgstr "" "/ - tìm má»™t khúc khá»›p vá»›i biểu thức chÃnh quy\n" "s - chia khúc hiện tại thà nh các khúc nhá» hÆ¡n\n" "e - sá»a bằng tay khúc hiện hà nh\n" -"p - in ra khúc hiện hà nh\n" +"p - in ra khúc hiện hà nh, 'P' để chạy trình phân trang\n" "? - hiển thị trợ giúp\n" +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Cần má»™t ký tá»±, nhưng lại có '%s'" + msgid "No previous hunk" msgstr "Không có khúc kế trước" @@ -613,9 +670,19 @@ msgstr "Chia nhá» thà nh %d khúc." msgid "Sorry, cannot edit this hunk" msgstr "Không thể sá»a khúc nà y" +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "không hiểu câu lệnh: '%s' ('?' để hiển thị trợ giúp)" + msgid "'git apply' failed" msgstr "'git apply' gặp lá»—i" +msgid "No changes." +msgstr "Không có thay đổi nà o." + +msgid "Only binary files changed." +msgstr "Chỉ có các táºp tin nhị phân thay đổi." + #, c-format msgid "" "\n" @@ -1215,6 +1282,15 @@ msgstr "đồng thá»i áp dụng bản vá (dùng vá»›i tùy chá»n --stat/--su msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "thá» hòa trá»™n kiểu three-way, quay lại kiểu bình thưá»ng nếu thất bại" +msgid "for conflicts, use our version" +msgstr "nếu xung đột, sá» dụng phiên bản cá»§a ta" + +msgid "for conflicts, use their version" +msgstr "nếu xung đột, sá» dụng phiên bản cá»§a há»" + +msgid "for conflicts, use a union version" +msgstr "nếu xung đột, sá» dụng phiên bản kết hợp" + msgid "build a temporary index based on embedded index information" msgstr "xây dá»±ng chỉ mục tạm thá»i dá»±a trên thông tin chỉ mục được nhúng" @@ -1261,6 +1337,9 @@ msgstr "thêm <gốc> và o trước tất cả các tên táºp tin" msgid "don't return error for empty patches" msgstr "đừng trả vá» lá»—i khi các bản vá trống rá»—ng" +msgid "--ours, --theirs, and --union require --3way" +msgstr "--ours, --theirs, và --union cần tuỳ chá»n --3way" + #, c-format msgid "cannot stream blob %s" msgstr "không thể stream blob '%s'" @@ -1333,6 +1412,10 @@ msgid "not a tree object: %s" msgstr "không phải là đối tượng cây: %s" #, c-format +msgid "failed to unpack tree object %s" +msgstr "gặp lá»—i khi giải nén đối tượng cây %s" + +#, c-format msgid "File not found: %s" msgstr "Không tìm thấy táºp tin: %s" @@ -1462,6 +1545,9 @@ msgstr "bá» qua táºp tin gitattributes quá lá»›n '%s'" msgid "ignoring overly large gitattributes blob '%s'" msgstr "bá» qua blob gitattributes quá lá»›n '%s'" +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "không thể dùng --attr-source hoặc GIT_ATTR_SOURCE mà không có kho chứa" + msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "--attr-source hoặc GIT_ATTR_SOURCE sai" @@ -1772,14 +1858,7 @@ msgid "cannot chmod %cx '%s'" msgstr "không thể chmod %cx '%s'" msgid "Unstaged changes after refreshing the index:" -msgstr "ÄÆ°a ra khá»i bệ phóng các thay đổi sau khi là m má»›i lại chỉ mục:" - -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"mục cà i đặt add.interactive.useBuiltin đã không còn!\n" -"Xem mục tin cá»§a nó trong 'git help config' để biết chi tiết." +msgstr "ÄÆ°a ra khá»i vùng chá» các thay đổi sau khi là m má»›i lại chỉ mục:" msgid "could not read the index" msgstr "Không thể Ä‘á»c chỉ mục" @@ -2065,8 +2144,8 @@ msgstr "Thân cá»§a lần chuyển giao là :" #, c-format msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " msgstr "" -"Ãp dụng? đồng ý [y]/khô[n]g/chỉnh sá»a [e]/hiển thị miếng [v]á/chấp nháºn tất " -"cả [a]: " +"Ãp dụng? đồng ý [y]/không [n]/chỉnh sá»a [e]/hiển thị bản vá [v]/chấp nháºn " +"tất cả [a]: " msgid "unable to write index file" msgstr "không thể ghi táºp tin chỉ mục" @@ -2110,9 +2189,8 @@ msgid "" "already introduced the same changes; you might want to skip this patch." msgstr "" "Không có thay đổi nà o - bạn đã quên sá» dụng lệnh 'git add' à ?\n" -"Nếu ở đây không có gì còn lại stage, tình cá» là có má»™t số thứ khác\n" -"đã sẵn được đưa và o vá»›i cùng ná»™i dung thay đổi; bạn có lẽ muốn bá» qua miếng " -"vá nà y." +"Nếu ở đây không còn gì để đưa và o vùng chá», có lẽ má»™t số ngưá»i khác\n" +"đã thêm các thay đổi trong nà y rồi; bạn có lẽ muốn bá» qua bản vá nà y." msgid "" "You still have unmerged paths in your index.\n" @@ -2121,8 +2199,8 @@ msgid "" "You might run `git rm` on a file to accept \"deleted by them\" for it." msgstr "" "Bạn vẫn có những đưá»ng dẫn chưa hòa trá»™n trong chỉ mục cá»§a bạn.\n" -"Bạn nên 'git add' từng táºp tin vá»›i các xung đột đã được giải quyết để đánh " -"dấu chúng là thế.\n" +"Bạn nên 'git add' những táºp tin đã giải quyết xung đột để đánh dấu chúng là " +"đã xong.\n" "Bạn có lẽ muốn chạy 'git rm' trên má»™t táºp tin để chấp nháºn \"được xóa bởi " "há»\" cho nó." @@ -2222,11 +2300,14 @@ msgstr "huá»· thao tác vá nhưng vẫn giữ HEAD nÆ¡i nó chỉ đến" msgid "show the patch being applied" msgstr "hiển thị bản vá đã được áp dụng rồi" +msgid "try to apply current patch again" +msgstr "thỠáp dụng bản vá hiện hà nh thêm lần nữa" + msgid "record the empty patch as an empty commit" msgstr "ghi lại bản vá trống rá»—ng như là má»™t lần chuyển giao trống" msgid "lie about committer date" -msgstr "nói dối vá» ngà y chuyển giao" +msgstr "là m giả ngà y chuyển giao" msgid "use current timestamp for author date" msgstr "dùng dấu thá»i gian hiện tại cho ngà y tác giả" @@ -2277,9 +2358,6 @@ msgstr "git apply [<các tùy chá»n>] [<miếng-vá>...]" msgid "could not redirect output" msgstr "không thể chuyển hướng đầu ra" -msgid "git archive: Remote with no URL" -msgstr "git archive: Máy chá»§ không có địa chỉ URL" - msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive: cần ACK/NAK, nhưng lại nháºn được gói flush" @@ -2435,9 +2513,6 @@ msgstr "" "tham số không hợp lệ %s cho 'git bisect terms'.\n" "Các tùy chá»n há»— trợ là : --term-good|--term-old và --term-bad|--term-new." -msgid "revision walk setup failed\n" -msgstr "gặp lá»—i cà i đặt việc di chuyển qua các Ä‘iểm xét duyệt\n" - #, c-format msgid "could not open '%s' for appending" msgstr "không thể mở '%s' để nối thêm" @@ -2603,7 +2678,7 @@ msgid "force progress reporting" msgstr "ép buá»™c báo cáo tiến độ công việc" msgid "show output score for blame entries" -msgstr "hiển thị kết xuất Ä‘iểm số cho các mục tin 'blame'" +msgstr "hiển thị Ä‘iểm số đầu ra cho các mục tin 'blame'" msgid "show original filename (Default: auto)" msgstr "hiển thị tên táºp tin gốc (Mặc định: auto)" @@ -2645,17 +2720,17 @@ msgid "ignore revisions from <file>" msgstr "bá» qua các Ä‘iểm xét duyệt từ <táºp tin>" msgid "color redundant metadata from previous line differently" -msgstr "siêu dữ liệu dư thừa mà u từ dòng trước khác hẳn" +msgstr "tô mà u khác cho siêu dữ liệu dư thừa từ dòng trước" msgid "color lines by age" -msgstr "các dòng mà u theo tuổi" +msgstr "tô mà u các dòng theo tuổi" msgid "spend extra cycles to find better match" -msgstr "tiêu thụ thêm năng tà i nguyên máy móc để tìm kiếm tốt hÆ¡n nữa" +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 Ä‘iểm xét duyệt (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" @@ -2881,7 +2956,7 @@ msgid "unset the upstream info" msgstr "bỠđặt thông tin thượng nguồn" msgid "use colored output" -msgstr "tô mà u kết xuất" +msgstr "tô mà u đầu ra" msgid "act on remote-tracking branches" msgstr "thao tác trên nhánh 'remote-tracking'" @@ -3175,6 +3250,9 @@ msgstr "Cần má»™t kho chứa để có thể tạo má»™t bundle." msgid "do not show bundle details" msgstr "không hiển thị chi tiết bundle (bó)" +msgid "need a repository to verify a bundle" +msgstr "cần má»™t kho chứa để thẩm tra má»™t bundle" + #, c-format msgid "%s is okay\n" msgstr "%s tốt\n" @@ -3288,7 +3366,7 @@ msgid "Change or optimize batch output" msgstr "Thay đổi hay tối ưu hóa đầu ra batch" msgid "buffer --batch output" -msgstr "đệm kết xuất --batch" +msgstr "buffer đầu ra --batch" msgid "follow in-tree symlinks" msgstr "theo liên kết má»m trong-cây" @@ -3409,9 +3487,14 @@ msgstr "git check-mailmap [<các tùy chá»n>] <danh-bạ>..." msgid "also read contacts from stdin" msgstr "đồng thá»i Ä‘á»c các danh bạ từ stdin" -#, c-format -msgid "unable to parse contact: %s" -msgstr "không thể Ä‘á»c danh bạ: '%s'" +msgid "read additional mailmap entries from file" +msgstr "Ä‘á»c thêm mục mailmap từ táºp-tin" + +msgid "blob" +msgstr "blob" + +msgid "read additional mailmap entries from blob" +msgstr "Ä‘á»c thêm mục mailmap từ blob" msgid "no contacts specified" msgstr "chưa chỉ ra danh bạ" @@ -3456,7 +3539,7 @@ msgid "write the content to temporary files" msgstr "ghi ná»™i dung và o táºp tin tạm" msgid "copy out the files from named stage" -msgstr "sao chép ra các táºp tin từ bệ phóng có tên" +msgstr "sao chép ra các táºp tin từ vùng chá» có tên" msgid "git checkout [<options>] <branch>" msgstr "git checkout [<các tùy chá»n>] <nhánh>" @@ -3550,7 +3633,7 @@ msgid "" "cannot continue with staged changes in the following files:\n" "%s" msgstr "" -"không thể tiếp tục vá»›i các thay đổi đã được đưa lên bệ phóng trong các dòng " +"không thể tiếp tục vá»›i các thay đổi đã được đưa và o vùng chá» trong các dòng " "sau:\n" "%s" @@ -3570,7 +3653,7 @@ msgstr "Äặt lại nhánh '%s'\n" #, c-format msgid "Already on '%s'\n" -msgstr "Äã sẵn sà ng trên '%s'\n" +msgstr "Äã sẵn ở trên '%s'\n" #, c-format msgid "Switched to and reset branch '%s'\n" @@ -3748,7 +3831,11 @@ msgstr "các đưá»ng dẫn không thể dùng cùng vá»›i các nhánh chuyển #, c-format msgid "'%s' cannot be used with switching branches" -msgstr "'%s' không thể được sá» dụng vá»›i các nhánh chuyển" +msgstr "'%s' không thể được sá» dụng khi chuyển nhánh" + +#, c-format +msgid "'%s' needs the paths to check out" +msgstr "'%s' cần đưá»ng dẫn để checkout" #, c-format msgid "'%s' cannot be used with '%s'" @@ -4177,12 +4264,20 @@ 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 được liên kết má»m %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 và '%s'" +msgstr "gặp lá»—i khi sao chép táºp tin tá»›i '%s'" #, c-format msgid "failed to iterate over '%s'" @@ -4512,7 +4607,7 @@ msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -4587,7 +4682,7 @@ msgid "updating files failed" msgstr "cáºp nháºt táºp tin gặp lá»—i" msgid "failed to unpack HEAD tree object" -msgstr "gặp lá»—i khi tháo dỡ HEAD đối tượng cây" +msgstr "gặp lá»—i khi giải nén đối tượng cây HEAD" msgid "No paths with --include/--only does not make sense." msgstr "Không đưá»ng dẫn vá»›i các tùy chá»n --include/--only không hợp lý." @@ -4841,7 +4936,7 @@ msgid "version" msgstr "phiên bản" msgid "machine-readable output" -msgstr "kết xuất dạng máy-có-thể-Ä‘á»c" +msgstr "xuất ra dạng máy-có-thể-Ä‘á»c" msgid "show status in long format (default)" msgstr "hiển thị trạng thái ở định dạng dà i (mặc định)" @@ -4930,15 +5025,14 @@ msgstr "" msgid "use autosquash formatted message to squash specified commit" msgstr "" -"dùng lá»i nhắn có định dạng tá»± động nén để nén lại các lần chuyển giao đã chỉ " -"ra" +"dùng lá»i nhắn có định dạng autosquash để squash các lần chuyển giao đã chỉ ra" msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "" "lần chuyển giao nháºn tôi là tác giả (được dùng vá»›i tùy chá»n -C/-c/--amend)" msgid "trailer" -msgstr "bá»™ dò vết" +msgstr "trailer" msgid "add custom trailer(s)" msgstr "thêm Ä‘uôi tá»± chá»n" @@ -5029,15 +5123,59 @@ msgstr "" "có bị đầy quá hay hạn nghạch đĩa (quota) bị vượt quá hay không,\n" "và sau đó \"git restore --staged :/\" để khắc phục." -msgid "git config [<options>]" -msgstr "git config [<các tùy chá»n>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<tuỳ-chá»n>] [<tuỳ-chá»n-hiển-thị>] [--includes]" -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "đối số không được thừa nháºn --type, %s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<tuỳ-chá»n>] [<tuỳ-chá»n-hiển-thị>] [--includes] [--all] [--" +"regexp] [--value=<giá-trị>] [--fixed-value] [--default=<giá-trị-mặc-định>] " +"<tên>" -msgid "only one type at a time" -msgstr "chỉ má»™t kiểu má»™t lần" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<tuỳ-chá»n>] [--type=<kiểu>] [--all] [--value=<giá-trị>] [--" +"fixed-value] <khoá> <giá-trị>" + +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<tuỳ-chá»n>] [--all] [--value=<giá-trị>] [--fixed-value] " +"<khoá> <giá-trị>" + +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<tuỳ-chá»n>] <tên-cÅ©> <tên-má»›i>" + +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<tuỳ-chá»n>] <tên>" + +msgid "git config edit [<file-option>]" +msgstr "git config edit [<tùy-chá»n>]" + +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "" +"git config [<tuỳ-chá»n>] --get-colorbool <tên> [<stdout-là -tty-hay-không>]" + +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<tuỳ-chá»n>] [<tuỳ-chá»n-hiển-thị>] [--includes] [--all] [--" +"regexp=<biểu-thức-chÃnh-quy>] [--value=<giá-trị>] [--fixed-value] [--" +"default=<giá-trị-mặc-định>] <khoá>" + +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<tuỳ-chá»n>] [--type=<kiểu>] [--comment=<chú-thÃch>] [--all] " +"[--value=<giá-trị>] [--fixed-value] <khoá> <giá-trị>" msgid "Config file location" msgstr "Vị trà táºp tin cấu hình" @@ -5063,54 +5201,6 @@ msgstr "blob-id" msgid "read config from given blob object" msgstr "Ä‘á»c cấu hình từ đối tượng blob đã cho" -msgid "Action" -msgstr "Hà nh động" - -msgid "get value: name [value-pattern]" -msgstr "lấy giá trị: tên [value-pattern]" - -msgid "get all values: key [value-pattern]" -msgstr "lấy tất cả giá trị: khóa [value-pattern]" - -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "lấy giá trị cho regexp: name-regex [value-pattern]" - -msgid "get value specific for the URL: section[.var] URL" -msgstr "lấy đặc tả giá trị cho URL: phần[.biến] URL" - -msgid "replace all matching variables: name value [value-pattern]" -msgstr "thay thế tất cả các biến khá»›p mẫu: tên giá-trị [value-pattern]" - -msgid "add a new variable: name value" -msgstr "thêm biến má»›i: tên giá-trị" - -msgid "remove a variable: name [value-pattern]" -msgstr "gỡ bá» biến: tên [value-pattern]" - -msgid "remove all matches: name [value-pattern]" -msgstr "gỡ bá» má»i cái khá»›p: tên [value-pattern]" - -msgid "rename section: old-name new-name" -msgstr "đổi tên phần: tên-cÅ© tên-má»›i" - -msgid "remove a section: name" -msgstr "gỡ bá» phần: tên" - -msgid "list all" -msgstr "liệt kê tất" - -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "sá» dụng so sánh bằng chuá»—i khi so sánh các giá trị vá»›i 'value-pattern'" - -msgid "open an editor" -msgstr "mở má»™t trình biên soạn" - -msgid "find the color configured: slot [default]" -msgstr "tìm cấu hình mà u sắc: slot [mặc định]" - -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "tìm các cà i đặt vá» mà u sắc: slot [stdout-là -tty]" - msgid "Type" msgstr "Kiểu" @@ -5138,8 +5228,8 @@ msgstr "giá trị là đưá»ng dẫn (tên táºp tin hay thư mục)" msgid "value is an expiry date" msgstr "giá trị là má»™t ngà y hết hạn" -msgid "Other" -msgstr "Khác" +msgid "Display options" +msgstr "Tuỳ chá»n hiển thị" msgid "terminate values with NUL byte" msgstr "kết thúc giá trị vá»›i byte NUL" @@ -5147,9 +5237,6 @@ msgstr "kết thúc giá trị vá»›i byte NUL" msgid "show variable names only" msgstr "chỉ hiển thị các tên biến" -msgid "respect include directives on lookup" -msgstr "tôn trá»ng kể cà các hướng trong tìm kiếm" - msgid "show origin of config (file, standard input, blob, command line)" msgstr "hiển thị nguồn gốc cá»§a cấu hình (táºp tin, stdin, blob, dòng lệnh)" @@ -5158,14 +5245,15 @@ msgstr "" "hiển thị phạm vi cá»§a cấu hình (cây là m việc, cục bá»™, toà n cầu, hệ thống, " "lệnh)" -msgid "value" -msgstr "giá trị" +msgid "show config keys in addition to their values" +msgstr "hiển thị khoá cùng vói giá trị" -msgid "with --get, use default value when missing entry" -msgstr "vá»›i --get, dùng giá trị mặc định khi thiếu mục tin" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "đối số không được thừa nháºn --type, %s" -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "ghi chú cho ngưá»i Ä‘á»c được (tá»± động thêm # và o trước nếu cần)" +msgid "only one type at a time" +msgstr "chỉ má»™t kiểu má»™t lần" #, c-format msgid "wrong number of arguments, should be %d" @@ -5241,47 +5329,72 @@ msgstr "" "worktreeConfig được báºt. Vui lòng Ä‘á»c phần \"CONFIGURATION FILE\"\n" "trong \"git help worktree\" để biết thêm chi tiết" -msgid "--get-color and variable type are incoherent" -msgstr "--get-color và kiểu biến là không mạch lạc" +msgid "Other" +msgstr "Khác" -msgid "only one action at a time" -msgstr "chỉ má»™t thao tác má»—i lần" +msgid "respect include directives on lookup" +msgstr "tôn trá»ng kể cà các hướng trong tìm kiếm" -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only chỉ được áp dụng cho --list hoặc --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "không thể Ä‘á»c táºp tin cấu hình '%s'" -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "" -"--show-origin chỉ được áp dụng cho --get, --get-all, --get-regexp, hoặc --" -"list" +msgid "error processing config file(s)" +msgstr "gặp lá»—i khi xá» lý các táºp tin cấu hình" -msgid "--default is only applicable to --get" -msgstr "--default chỉ được áp dụng cho --get" +msgid "Filter options" +msgstr "Tùy chá»n lá»c" -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment chỉ được áp dụng cho thao tác add/set/replace" +msgid "return all values for multi-valued config options" +msgstr "trả vá» tất cả giá trị cho tuỳ chá»n cấu hình Ä‘a trị" + +msgid "interpret the name as a regular expression" +msgstr "coi khoá là biểu thức chÃnh quy" + +msgid "show config with values matching the pattern" +msgstr "hiển thị giá trị cấu hình khá»›p vá»›i mẫu" + +msgid "use string equality when comparing values to value pattern" +msgstr "sá» dụng so sánh xâu khi so sánh các giá trị vá»›i mẫu" + +msgid "URL" +msgstr "URL" + +msgid "show config matching the given URL" +msgstr "hiển thị giá trị cấu hình khá»›p vá»›i URL" + +msgid "value" +msgstr "giá trị" + +msgid "use default value when missing entry" +msgstr "dùng giá trị mặc định khi không tồn tại" msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value chỉ áp dụng vá»›i 'value-pattern'" -#, c-format -msgid "unable to read config file '%s'" -msgstr "không thể Ä‘á»c táºp tin cấu hình '%s'" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= không thể được dùng vá»›i --all hay --url" -msgid "error processing config file(s)" -msgstr "gặp lá»—i khi xá» lý các táºp tin cấu hình" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= không thể được dùng vá»›i --all, --regexp hay --value" -msgid "editing stdin is not supported" -msgstr "sá»a chữa stdin là không được há»— trợ" +msgid "Filter" +msgstr "Bá»™ lá»c" -msgid "editing blobs is not supported" -msgstr "việc sá»a chữa các blob là không được há»— trợ" +msgid "replace multi-valued config option with new value" +msgstr "thay thế tuỳ chá»n cấu hình Ä‘a trị thà nh giá trị" -#, c-format -msgid "cannot create configuration file %s" -msgstr "không thể tạo táºp tin cấu hình '%s'" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "ghi chú cho ngưá»i Ä‘á»c được (tá»± động thêm # và o trước nếu cần)" + +msgid "add a new line without altering any existing values" +msgstr "thêm dòng má»›i giữ nguyên các giá trị cÅ©" + +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value chỉ áp dụng vá»›i --value=<mẫu>" + +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append không thể được dùng vá»›i --value=<mẫu>" #, c-format msgid "" @@ -5295,6 +5408,86 @@ msgstr "" msgid "no such section: %s" msgstr "không có Ä‘oạn: %s" +msgid "editing stdin is not supported" +msgstr "sá»a chữa stdin là không được há»— trợ" + +msgid "editing blobs is not supported" +msgstr "việc sá»a chữa các blob là không được há»— trợ" + +#, c-format +msgid "cannot create configuration file %s" +msgstr "không thể tạo táºp tin cấu hình '%s'" + +msgid "Action" +msgstr "Hà nh động" + +msgid "get value: name [<value-pattern>]" +msgstr "lấy giá trị: khoá [<mẫu-giá-trị>]" + +msgid "get all values: key [<value-pattern>]" +msgstr "lấy tất cả giá trị: khóa [<mẫu-giá-trị>]" + +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "lấy giá trị cho biểu thức chÃnh quy: regex [<mẫu-giá-trị>]" + +msgid "get value specific for the URL: section[.var] URL" +msgstr "lấy giá trị riêng cho URL: phần[.biến] URL" + +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "thay thế tất cả các biến khá»›p mẫu: tên giá-trị [<mẫu-giá-trị>]" + +msgid "add a new variable: name value" +msgstr "thêm biến má»›i: tên giá-trị" + +msgid "remove a variable: name [<value-pattern>]" +msgstr "gỡ bá» biến: tên [<mẫu-giá-trị>]" + +msgid "remove all matches: name [<value-pattern>]" +msgstr "gỡ bá» má»i biến khá»›p: tên [<mẫu-giá-trị>]" + +msgid "rename section: old-name new-name" +msgstr "đổi tên phần: tên-cÅ© tên-má»›i" + +msgid "remove a section: name" +msgstr "gỡ bá» phần: tên" + +msgid "list all" +msgstr "liệt kê tất" + +msgid "open an editor" +msgstr "mở má»™t trình biên soạn" + +msgid "find the color configured: slot [<default>]" +msgstr "tìm cấu hình mà u sắc: slot [<mặc định>]" + +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "tìm các cà i đặt vá» mà u sắc: slot [<stdout-là -tty-hay-không>]" + +msgid "with --get, use default value when missing entry" +msgstr "vá»›i --get, dùng giá trị mặc định khi thiếu mục tin" + +msgid "--get-color and variable type are incoherent" +msgstr "--get-color và kiểu biến là không mạch lạc" + +msgid "no action specified" +msgstr "chưa chỉ ra hà nh động" + +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only chỉ được áp dụng cho --list hoặc --get-regexp" + +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"--show-origin chỉ được áp dụng cho --get, --get-all, --get-regexp, hoặc --" +"list" + +msgid "--default is only applicable to --get" +msgstr "--default chỉ được áp dụng cho --get" + +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment chỉ được áp dụng cho thao tác add/set/replace" + msgid "print sizes in human readable format" msgstr "hiển thị kÃch cỡ theo định dạng dà nh cho ngưá»i Ä‘á»c" @@ -5637,7 +5830,7 @@ msgid "use the done feature to terminate the stream" msgstr "sá» dụng tÃnh năng done để kết thúc luồng dữ liệu" msgid "skip output of blob data" -msgstr "bá» qua kết xuất cá»§a dữ liệu blob" +msgstr "bá» qua đầu ra cá»§a dữ liệu blob" msgid "refspec" msgstr "refspec" @@ -5646,7 +5839,7 @@ msgid "apply refspec to exported refs" msgstr "áp dụng refspec cho refs đã xuất" msgid "anonymize output" -msgstr "kết xuất anonymize" +msgstr "ẩn danh đầu ra" msgid "from:to" msgstr "từ:đến" @@ -5778,8 +5971,8 @@ msgstr "" "để tránh kiểm tra nà y\n" #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s đã không gá»i tất cả các đối tượng cần thiết\n" +msgid "%s did not send all necessary objects" +msgstr "%s đã không gá»i tất cả các đối tượng cần thiết" #, c-format msgid "rejected %s because shallow roots are not allowed to be updated" @@ -5816,8 +6009,8 @@ msgid "option \"%s\" value \"%s\" is not valid for %s" msgstr "tùy chá»n \"%s\" có giá trị \"%s\" là không hợp lệ cho %s" #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "tùy chá»n \"%s\" bị bá» qua vá»›i %s\n" +msgid "option \"%s\" is ignored for %s" +msgstr "tùy chá»n \"%s\" bị bá» qua vá»›i %s" #, c-format msgid "%s is not a valid object" @@ -5946,7 +6139,7 @@ msgid "re-fetch without negotiating common commits" msgstr "re-fetch mà không dà n xếp các lần chuyển giao chung" msgid "prepend this to submodule path output" -msgstr "soạn sẵn cái nà y cho kết xuất đưá»ng dẫn mô-Ä‘un-con" +msgstr "soạn sẵn cái nà y cho đầu ra đưá»ng dẫn mô-Ä‘un-con" msgid "" "default for recursive fetching of submodules (lower priority than config " @@ -6038,7 +6231,7 @@ msgid "populate log with at most <n> entries from shortlog" msgstr "gắn nháºt ký vá»›i Ãt nhất <n> mục từ lệnh 'shortlog'" msgid "alias for --log (deprecated)" -msgstr "bà danh cho --log (đã lạc háºu)" +msgstr "đồng nghÄ©a vá»›i --log (đã không còn)" msgid "text" msgstr "văn bản" @@ -6119,6 +6312,9 @@ msgstr "config" msgid "config key storing a list of repository paths" msgstr "khóa cấu hình lưu trữ danh sách đưá»ng dẫn kho lưu trữ" +msgid "keep going even if command fails in a repository" +msgstr "tiếp tục dù có lệnh thất bại trong kho chứa" + msgid "missing --config=<config>" msgstr "thiếu --config=<config>" @@ -6141,7 +6337,7 @@ msgstr "có cảnh báo trong %s %s: %s" #, c-format msgid "broken link from %7s %s" -msgstr "liên kết gãy từ %7s %s" +msgstr "liên kết há»ng từ %7s %s" msgid "wrong object type in link" msgstr "kiểu đối tượng sai trong liên kết" @@ -6151,7 +6347,7 @@ msgid "" "broken link from %7s %s\n" " to %7s %s" msgstr "" -"liên kết gãy từ %7s %s \n" +"liên kết há»ng từ %7s %s \n" " tá»›i %7s %s" msgid "Checking connectivity" @@ -6486,7 +6682,10 @@ msgid "be more thorough (increased runtime)" msgstr "cẩn tháºn hÆ¡n nữa (tăng thá»i gian chạy)" msgid "enable auto-gc mode" -msgstr "báºt chế độ auto-gc" +msgstr "báºt chế độ auto-gc (tá»± động dá»n rác)" + +msgid "perform garbage collection in the background" +msgstr "tiến hà nh gc (dá»n rác) trong ná»n" msgid "force running gc even if there may be another gc running" msgstr "buá»™c gc chạy ngay cả khi có tiến trình gc khác Ä‘ang chạy" @@ -6585,6 +6784,9 @@ msgstr "nhiệm vụ '%s' không được chá»n nhiá»u lần" msgid "run tasks based on the state of the repository" msgstr "chạy nhiệm vụ dá»±a trên trạng thái cá»§a kho chứa" +msgid "perform maintenance in the background" +msgstr "tiến hà nh bảo trì trong ná»n" + msgid "frequency" msgstr "tần số" @@ -6858,16 +7060,16 @@ msgid "combine patterns specified with -e" msgstr "tổ hợp mẫu được chỉ ra vá»›i tùy chá»n -e" msgid "indicate hit with exit status without output" -msgstr "đưa ra gợi ý vá»›i trạng thái thoát mà không có kết xuất" +msgstr "chỉ ra có khá»›p mẫu hay không vá»›i trạng thái thoát thay vì đầu ra" msgid "show only matches from files that match all patterns" msgstr "chỉ hiển thị những cái khá»›p từ táºp tin mà nó khá»›p toà n bá»™ các mẫu" msgid "pager" -msgstr "dà n trang" +msgstr "trình phân trang" msgid "show matching files in the pager" -msgstr "hiển thị các táºp tin khá»›p trong trang giấy" +msgstr "hiển thị các táºp tin khá»›p trong trình phân trang" msgid "allow calling of grep(1) (ignored by this build)" msgstr "cho phép gá»i grep(1) (bị bá» qua bởi lần dịch nà y)" @@ -7353,7 +7555,7 @@ msgid "edit files in place" msgstr "sá»a các táºp tin tại chá»—" msgid "trim empty trailers" -msgstr "cắt bá» phần trống thừa ở Ä‘uôi" +msgstr "cắt bá» phần trailer trống ở Ä‘uôi" msgid "placement" msgstr "vị trÃ" @@ -7402,7 +7604,7 @@ msgid "invalid --decorate option: %s" msgstr "tùy chá»n --decorate không hợp lệ: %s" msgid "suppress diff output" -msgstr "chặn má»i kết xuất từ diff" +msgstr "chặn má»i đầu ra từ diff" msgid "show source" msgstr "hiển thị mã nguồn" @@ -7435,10 +7637,7 @@ msgstr "-L<vùng>:<táºp tin> không thể được sá» dụng vá»›i đặc tẠ#, c-format msgid "Final output: %d %s\n" -msgstr "Kết xuất cuối cùng: %d %s\n" - -msgid "unable to create temporary object directory" -msgstr "không thể tạo thư mục đối tượng tạm thá»i" +msgstr "Äầu ra cuối cùng: %d %s\n" #, c-format msgid "git show %s: bad file" @@ -7487,7 +7686,7 @@ msgid "git format-patch [<options>] [<since> | <revision-range>]" msgstr "git format-patch [<các tùy chá»n>] [<kể-từ> | <vùng-xem-xét>]" msgid "two output directories?" -msgstr "hai thư mục kết xuất?" +msgstr "hai thư mục đầu ra?" #, c-format msgid "unknown commit %s" @@ -7563,8 +7762,11 @@ msgstr "đánh dấu chuá»—i là lần chạy lại thứ N" msgid "max length of output filename" msgstr "chiá»u dà i tên táºp tin đầu ra tối Ä‘a" -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "dùng [RFC PATCH] thay cho [PATCH]" +msgid "rfc" +msgstr "rfc" + +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "thêm <rfc> (mặc định 'RFC') trước 'PATCH'" msgid "cover-from-description-mode" msgstr "cover-from-description-mode" @@ -7585,7 +7787,7 @@ msgid "don't strip/add [PATCH]" msgstr "không loại bá»/thêm [PATCH]" msgid "don't output binary diffs" -msgstr "không kết xuất diff nhị phân" +msgstr "không xuất diff nhị phân" msgid "output all-zero hash in From header" msgstr "xuất má»i mã băm all-zero trong phần đầu From" @@ -7722,7 +7924,7 @@ msgid "Generating patches" msgstr "Äang tạo các bản vá" msgid "failed to create output files" -msgstr "gặp lá»—i khi tạo các táºp tin kết xuất" +msgstr "gặp lá»—i khi tạo các táºp tin đầu ra" msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]" msgstr "git cherry [-v] [<thượng-nguồn> [<đầu> [<giá»›i-hạn>]]]" @@ -7759,19 +7961,19 @@ msgid "show cached files in the output (default)" msgstr "hiển thị các táºp tin được nhá»› tạm và o đầu ra (mặc định)" msgid "show deleted files in the output" -msgstr "hiển thị các táºp tin đã xóa trong kết xuất" +msgstr "hiển thị các táºp tin đã xóa trong đầu ra" msgid "show modified files in the output" -msgstr "hiển thị các táºp tin đã bị sá»a đổi ra kết xuất" +msgstr "hiển thị các táºp tin đã bị sá»a đổi ra đầu ra" msgid "show other files in the output" -msgstr "hiển thị các táºp tin khác trong kết xuất" +msgstr "hiển thị các táºp tin khác trong đầu ra" msgid "show ignored files in the output" -msgstr "hiển thị các táºp tin bị bá» qua trong kết xuất" +msgstr "hiển thị các táºp tin bị bá» qua trong đầu ra" msgid "show staged contents' object name in the output" -msgstr "hiển thị tên đối tượng cá»§a ná»™i dung được đặt lên bệ phóng ra kết xuất" +msgstr "hiển thị tên đối tượng cá»§a ná»™i dung được đặt và o vùng chá» ra đầu ra" msgid "show files on the filesystem that need to be removed" msgstr "hiển thị các táºp tin trên hệ thống táºp tin mà nó cần được gỡ bá»" @@ -7786,13 +7988,13 @@ msgid "don't show empty directories" msgstr "không hiển thị thư mục rá»—ng" msgid "show unmerged files in the output" -msgstr "hiển thị các táºp tin chưa hòa trá»™n trong kết xuất" +msgstr "hiển thị các táºp tin chưa hòa trá»™n trong đầu ra" msgid "show resolve-undo information" msgstr "hiển thị thông tin resolve-undo" msgid "skip files matching pattern" -msgstr "bá» qua những táºp tin khá»›p vá»›i má»™t mẫu" +msgstr "bá» qua những táºp tin khá»›p vá»›i mẫu" msgid "read exclude patterns from <file>" msgstr "Ä‘á»c mẫu cần loại trừ từ <táºp-tin>" @@ -7804,10 +8006,10 @@ msgid "add the standard git exclusions" msgstr "thêm loại trừ tiêu chuẩn kiểu git" msgid "make the output relative to the project top directory" -msgstr "là m cho kết xuất liên quan đến thư mục ở mức cao nhất (gốc) cá»§a dá»± án" +msgstr "cho kết quả là đưá»ng dẫn tương đối từ thư mục gốc cá»§a dá»± án" msgid "if any <file> is not in the index, treat this as an error" -msgstr "nếu <táºp tin> bất kỳ không ở trong chỉ mục, xá» lý nó như má»™t lá»—i" +msgstr "nếu có bất kỳ <táºp tin> không ở trong chỉ mục, coi nó như má»™t lá»—i" msgid "tree-ish" msgstr "tree-ish" @@ -7833,11 +8035,11 @@ msgstr "" "deduplicate, --eol" msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<kho> [<mẫu>...]]" @@ -7853,8 +8055,11 @@ msgstr "đưá»ng dẫn cá»§a git-upload-pack trên máy chá»§" msgid "limit to tags" msgstr "giá»›i hạn tá»›i các thẻ" -msgid "limit to heads" -msgstr "giá»›i hạn cho các đầu" +msgid "limit to branches" +msgstr "giá»›i hạn tá»›i các nhánh" + +msgid "deprecated synonym for --branches" +msgstr "trước đây là đồng nghÄ©a vá»›i --branches" msgid "do not show peeled tags" msgstr "không hiển thị thẻ bị peel (gá»t bá»)" @@ -8002,15 +8207,6 @@ msgstr "dùng kiểu hòa dá»±a trên diff3" msgid "use a zealous diff3 based merge" msgstr "dùng kiểu hòa trá»™n dá»±a trên 'zealous diff3'" -msgid "for conflicts, use our version" -msgstr "nếu xung đột, sá» dụng phiên bản cá»§a ta" - -msgid "for conflicts, use their version" -msgstr "nếu xung đột, sá» dụng phiên bản cá»§a há»" - -msgid "for conflicts, use a union version" -msgstr "nếu xung đột, sá» dụng phiên bản kết hợp" - msgid "<algorithm>" msgstr "<thuáºt toán>" @@ -8482,6 +8678,9 @@ msgstr "gói được sá» dụng khi tÃnh toán má»™t \"multi-pack bitmap\"" msgid "write multi-pack bitmap" msgstr "ghi multi-pack bitmap" +msgid "write a new incremental MIDX" +msgstr "ghi incremental MIDX má»›i" + msgid "write multi-pack index containing only given indexes" msgstr "ghi chỉ mục multi-pack chỉ chứa các chỉ mục đã cho" @@ -8694,7 +8893,7 @@ msgid "Write/edit the notes for the following object:" msgstr "Ghi hay sá»a ghi chú cho đối tượng sau đây:" msgid "could not read 'show' output" -msgstr "không thể Ä‘á»c kết xuất 'show'" +msgstr "không thể Ä‘á»c đầu ra 'show'" #, c-format msgid "failed to finish 'show' for object '%s'" @@ -9171,7 +9370,7 @@ msgid "use threads when searching for best delta matches" msgstr "sá» dụng các tuyến trình khi tìm kiếm cho các mẫu khá»›p delta tốt nhất" msgid "do not create an empty pack output" -msgstr "không thể tạo kết xuất gói trống rá»—ng" +msgstr "không thể tạo đầu ra gói trống rá»—ng" msgid "read revision arguments from standard input" msgstr "Ä‘á»c tham số 'revision' từ stdin" @@ -9300,7 +9499,7 @@ msgid "" "Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-" "reused %<PRIu32> (from %<PRIuMAX>)" msgstr "" -"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>),dùng " +"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>), dùng " "lại pack %<PRIu32> (trong số %<PRIuMAX>)" msgid "" @@ -9862,10 +10061,10 @@ msgid "passed to 'git log'" msgstr "chuyển cho 'git log'" msgid "only emit output related to the first range" -msgstr "chỉ phát ra kết xuất liên quan đến vùng đầu tiên" +msgstr "chỉ phát ra kết quả liên quan đến vùng đầu tiên" msgid "only emit output related to the second range" -msgstr "chỉ phát ra kết xuất liên quan đến vùng thứ hai" +msgstr "chỉ phát ra kết quả liên quan đến vùng thứ hai" #, c-format msgid "not a revision: '%s'" @@ -10029,7 +10228,7 @@ msgstr "" "không thể tổ hợp các tùy chá»n áp dụng vá»›i các tùy chá»n hòa trá»™n vá»›i nhau" msgid "--empty=ask is deprecated; use '--empty=stop' instead." -msgstr "không cho dùng --empty=ask nữa; hãy thay thế bằng '--empty=stop'." +msgstr "không còn dùng --empty=ask nữa; hãy thay thế bằng '--empty=stop'." #, c-format msgid "" @@ -10499,6 +10698,31 @@ 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 verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +msgid "specify the reference format to convert to" +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 "missing --ref-format=<format>" +msgstr "thiếu --ref-format=<định dạng>" + +#, c-format +msgid "repository already uses '%s' format" +msgstr "kho đã dùng định dạng '%s'" + +msgid "enable strict checking" +msgstr "cho phép kiểm tra nghiêm ngặt" + +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' không nháºn tham số" + msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" "mirror=<fetch|push>] <name> <url>" @@ -10778,9 +11002,6 @@ msgstr "* máy chá»§ %s" msgid " Fetch URL: %s" msgstr " URL để lấy vá»: %s" -msgid "(no URL)" -msgstr "(không có URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -10789,6 +11010,9 @@ msgstr "(không có URL)" msgid " Push URL: %s" msgstr " URL để đẩy lên: %s" +msgid "(no URL)" +msgstr "(không có URL)" + #, c-format msgid " HEAD branch: %s" msgstr " Nhánh HEAD: %s" @@ -10891,10 +11115,6 @@ msgstr "truy vấn đẩy URL thay vì lấy" msgid "return all URLs" msgstr "trả vá» má»i URL" -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "không có URL nà o được cấu hình cho nhánh '%s'" - msgid "manipulate push URLs" msgstr "đẩy các 'URL' bằng tay" @@ -11260,7 +11480,7 @@ msgid "--convert-graft-file takes no argument" msgstr "--convert-graft-file không nháºn đối số" msgid "only one pattern can be given with -l" -msgstr "chỉ má»™t mẫu được chỉ ra vá»›i tùy chá»n -l" +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" @@ -11422,7 +11642,7 @@ msgstr "Gặp lá»—i khi phân giải '%s' như là má»™t cây (tree) hợp lệ. msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead." msgstr "" -"không cho dùng --mixed vá»›i các đưá»ng dẫn nữa; hãy thay thế bằng lệnh 'git " +"không còn dùng --mixed vá»›i các đưá»ng dẫn nữa; hãy thay thế bằng lệnh 'git " "reset -- </các/đưá»ng/dẫn>'." #, c-format @@ -11434,7 +11654,7 @@ msgid "%s reset is not allowed in a bare repository" msgstr "%s reset không được phép trên kho chứa bare" msgid "Unstaged changes after reset:" -msgstr "Những thay đổi được đưa ra khá»i bệ phóng sau khi reset:" +msgstr "Những thay đổi được đưa ra khá»i vùng chá» sau khi reset:" #, c-format msgid "" @@ -11477,7 +11697,7 @@ msgid "stop parsing after the first non-option argument" msgstr "dừng Ä‘á»c sau đối số đầu tiên không có tùy chá»n" msgid "output in stuck long form" -msgstr "kết xuất trong định dạng gáºy dà i" +msgstr "kết quả có định dạng dà i" msgid "premature end of input" msgstr "đầu và o kết thúc bất thưá»ng" @@ -11646,7 +11866,7 @@ msgid_plural "" "the following files have staged content different from both the\n" "file and the HEAD:" msgstr[0] "" -"các táºp tin sau đây có khác biệt ná»™i dung đã đưa lên bệ phóng\n" +"các táºp tin sau đây có khác biệt ná»™i dung đã đưa và o vùng chá»\n" "từ cả táºp tin và cả HEAD:" msgid "" @@ -11751,7 +11971,7 @@ msgid "group by committer rather than author" msgstr "nhóm theo ngưá»i chuyển giao thay vì tác giả" msgid "sort output according to the number of commits per author" -msgstr "sắp xếp kết xuất tuân theo số lượng chuyển giao trên má»—i tác giả" +msgstr "sắp xếp kết quả theo số lượng chuyển giao trên má»—i tác giả" msgid "suppress commit descriptions, only provides commit count" msgstr "chặn má»i mô tả lần chuyển giao, chỉ đưa ra số lượng lần chuyển giao" @@ -11883,12 +12103,12 @@ msgstr "Không hiểu thuáºt toán băm dữ liệu" msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<mẫu>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<mẫu>...]" msgid "" "git show-ref --verify [-q | --quiet] [-d | --dereference]\n" @@ -11911,11 +12131,11 @@ msgstr "tham chiếu không tồn tại" msgid "failed to look up reference" msgstr "gặp lá»—i khi tìm tham chiếu" -msgid "only show tags (can be combined with heads)" -msgstr "chỉ hiển thị thẻ (có thể tổ hợp cùng vá»›i đầu)" +msgid "only show tags (can be combined with --branches)" +msgstr "chỉ hiển thị thẻ (có thể kết hợp vá»›i --branches)" -msgid "only show heads (can be combined with tags)" -msgstr "chỉ hiển thị đầu (có thể tổ hợp cùng vá»›i thẻ)" +msgid "only show branches (can be combined with --tags)" +msgstr "chỉ hiển thị đầu (có thể kết hợp vá»›i --tags)" msgid "check for reference existence without resolving" msgstr "kiểm tra tồn tại tham chiếu nhưng không phân giải" @@ -11967,6 +12187,10 @@ msgstr "gặp lá»—i khi gỡ bá» thư mục \"%s\"" msgid "failed to create directory for sparse-checkout file" msgstr "gặp lá»—i khi tạo thư mục cho táºp tin sparse-checkout" +#, c-format +msgid "unable to fdopen %s" +msgstr "không thể fdopen %s" + msgid "failed to initialize worktree config" msgstr "gặp lá»—i khi khởi tạo cấu hình cây là m việc" @@ -12210,7 +12434,7 @@ msgid "failed to parse tree" msgstr "gặp lá»—i khi Ä‘á»c cây" msgid "failed to unpack trees" -msgstr "gặp lá»—i khi tháo dỡ cây" +msgstr "gặp lá»—i khi giải nén cây" msgid "include untracked files in the stash" msgstr "bao gồm các táºp tin không được theo dõi trong stash" @@ -12229,7 +12453,7 @@ msgid "\"git stash store\" requires one <commit> argument" msgstr "\"git stash store\" cần má»™t đối số <lần chuyển giao>" msgid "No staged changes" -msgstr "Không có thay đổi đã được đưa lên bệ phóng" +msgstr "Không có thay đổi đã được đưa và o vùng chá»" msgid "No changes selected" msgstr "Chưa có thay đổi nà o được chá»n" @@ -12247,7 +12471,7 @@ msgid "Cannot save the current worktree state" msgstr "Không thể ghi lại trạng thái cây-là m-việc hiện hà nh" msgid "Cannot save the current staged state" -msgstr "Không thể ghi lại trạng thái bệ phóng hiện hà nh" +msgstr "Không thể ghi lại trạng thái vùng chá» hiện hà nh" msgid "Cannot record working tree state" msgstr "Không thể ghi lại trạng thái cây là m việc hiện hà nh" @@ -12281,7 +12505,7 @@ msgid "keep index" msgstr "giữ nguyên chỉ mục" msgid "stash staged changes only" -msgstr "chỉ tạm cất Ä‘i các thay đổi đã đưa lên bệ phóng" +msgstr "chỉ tạm cất Ä‘i các thay đổi đã đưa và o vùng chá»" msgid "stash in patch mode" msgstr "cất Ä‘i ở chế độ vá" @@ -12344,7 +12568,7 @@ msgstr "" "." msgid "suppress output of entering each submodule command" -msgstr "chặn kết xuất cá»§a từng lệnh mô-Ä‘un-con" +msgstr "chặn đầu ra cá»§a từng lệnh mô-Ä‘un-con" msgid "recurse into nested submodules" msgstr "đệ quy và o trong mô-Ä‘un-con lồng nhau" @@ -12369,7 +12593,7 @@ msgid "Failed to register update mode for submodule path '%s'" msgstr "Gặp lá»—i khi đăng ký chế độ cáºp nháºt cho đưá»ng dẫn mô-Ä‘un-con '%s'" msgid "suppress output for initializing a submodule" -msgstr "chặn kết xuất cá»§a khởi tạo má»™t mô-Ä‘un-con" +msgstr "chặn đầu ra cá»§a khởi tạo má»™t mô-Ä‘un-con" msgid "git submodule init [<options>] [<path>]" msgstr "git submodule init [<các tùy chá»n>] [</đưá»ng/dẫn>]" @@ -12389,7 +12613,7 @@ msgid "failed to recurse into submodule '%s'" msgstr "gặp lá»—i khi đệ quy và o trong mô-Ä‘un-con '%s'" msgid "suppress submodule status output" -msgstr "chặn kết xuất vá» tình trạng mô-Ä‘un-con" +msgstr "chặn đầu ra vá» tình trạng mô-Ä‘un-con" msgid "" "use commit stored in the index instead of the one stored in the submodule " @@ -12421,8 +12645,8 @@ msgid "couldn't hash object from '%s'" msgstr "không thể băm đối tượng từ '%s'" #, c-format -msgid "unexpected mode %o\n" -msgstr "gặp chế độ không như mong chá» %o\n" +msgid "unexpected mode %o" +msgstr "gặp chế độ không rõ %o" msgid "use the commit stored in the index instead of the submodule HEAD" msgstr "hùng lần chuyển giao đã lưu trong chỉ mục thay cho HEAD mô-Ä‘un-con" @@ -12458,7 +12682,7 @@ msgid "failed to update remote for submodule '%s'" msgstr "gặp lá»—i khi cáºp nháºt cho mô-Ä‘un-con '%s'" msgid "suppress output of synchronizing submodule url" -msgstr "chặn kết xuất cá»§a url mô-Ä‘un-con đồng bá»™" +msgstr "chặn đầu ra cá»§a url mô-Ä‘un-con đồng bá»™" msgid "git submodule sync [--quiet] [--recursive] [<path>]" msgstr "git submodule sync [--quiet] [--recursive] [</đưá»ng/dẫn>]" @@ -12545,14 +12769,14 @@ msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "từ chối tạo/dùng '%s' trong má»™t thư mục git cá»§a mô Ä‘un con" #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "việc sao '%s' và o đưá»ng dẫn mô-Ä‘un-con '%s' gặp lá»—i" - -#, c-format msgid "directory not empty: '%s'" msgstr "thư mục không trống: '%s'" #, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "việc sao '%s' và o đưá»ng dẫn mô-Ä‘un-con '%s' gặp lá»—i" + +#, c-format msgid "could not get submodule directory for '%s'" msgstr "không thể lấy thư mục mô-Ä‘un-con cho '%s'" @@ -12902,7 +13126,7 @@ msgid "delete symbolic ref" msgstr "xóa tham chiếu má»m" msgid "shorten ref output" -msgstr "là m ngắn kết xuất ref (tham chiếu)" +msgstr "là m ngắn kết quả ref (tham chiếu)" msgid "recursively dereference (default)" msgstr "chế độ giải tham chiếu đệ quy (mặc định)" @@ -12915,9 +13139,11 @@ msgstr "lý do cáºp nháºt" msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <táºp-tin>] [-e]\n" +" [(--trailer <token>[(=|:)<giá-trị>])...]\n" " <tên-thẻ> [<lần chuyển giao> | <đối tượng> ]" msgid "git tag -d <tagname>..." @@ -13353,7 +13579,7 @@ msgid "print commit contents" msgstr "hiển thị ná»™i dung cá»§a lần chuyển giao" msgid "print raw gpg status output" -msgstr "in kết xuất trạng thái gpg dạng thô" +msgstr "in đầu ra trạng thái gpg dạng thô" msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <gói>.idx..." @@ -13764,9 +13990,6 @@ msgstr "phần đầu không được thừa nháºn: %s%s (%d)" msgid "Repository lacks these prerequisite commits:" msgstr "Kho chứa thiếu những lần chuyển giao tiên quyết nà y:" -msgid "need a repository to verify a bundle" -msgstr "cần má»™t kho chứa để thẩm tra má»™t bundle" - msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -14029,7 +14252,7 @@ msgstr "" "Rút trÃch mã số lần chuyển giao từ má»™t kho nén đã được tạo bởi git-archive" msgid "Print lines matching a pattern" -msgstr "In ra những dòng khá»›p vá»›i má»™t mẫu" +msgstr "In ra những dòng khá»›p vá»›i mẫu" msgid "A portable graphical interface to Git" msgstr "Má»™t giao diện đồ há»a khả chuyển cho Git" @@ -14174,6 +14397,9 @@ msgstr "Nháºn cái mà được đẩy và o trong kho" msgid "Manage reflog information" msgstr "Quản lý thông tin reflog" +msgid "Low-level access to refs" +msgstr "Truy cáºp tá»›i tham chiếu ở mức thấp" + msgid "Manage set of tracked repositories" msgstr "Quản lý táºp hợp các kho chứa đã được theo dõi" @@ -14219,16 +14445,16 @@ msgid "Push objects over Git protocol to another repository" msgstr "Äẩy các đối tượng lên thông qua giao thức Git đến kho chứa khác" msgid "Git's i18n setup code for shell scripts" -msgstr "Mã cà i đặt quốc tế hóa cá»§a Git cho văn lệnh hệ vá»" +msgstr "Mã cà i đặt quốc tế hóa cá»§a Git cho shell script" msgid "Common Git shell script setup code" -msgstr "Mã cà i đặt văn lệnh hệ vá» Git chung" +msgstr "Mã cà i đặt shell script Git chung" msgid "Restricted login shell for Git-only SSH access" -msgstr "Hệ vỠđăng nháºp có hạn chế cho truy cáºp SSH chỉ-Git" +msgstr "Shell đăng nháºp có hạn chế cho truy cáºp SSH chỉ-Git" msgid "Summarize 'git log' output" -msgstr "Kết xuất 'git log' dạng tóm tắt" +msgstr "Tóm tắt kết quả 'git log'" msgid "Show various types of objects" msgstr "Hiển thị các kiểu khác nhau cá»§a các đối tượng" @@ -14248,7 +14474,7 @@ msgstr "" "dõi" msgid "Add file contents to the staging area" -msgstr "Thêm ná»™i dung táºp tin và o vùng bệ phóng" +msgstr "Thêm ná»™i dung táºp tin và o vùng vùng chá»" msgid "Stash the changes in a dirty working directory away" msgstr "Tạm cất Ä‘i các thay đổi trong má»™t thư mục là m việc bẩn" @@ -14266,7 +14492,7 @@ msgid "Bidirectional operation between a Subversion repository and Git" msgstr "Thao tác hai hướng giữ hai kho Subversion và Git" msgid "Switch branches" -msgstr "Các nhánh chuyển" +msgstr "Chuyển sang nhánh khác" msgid "Read, modify and delete symbolic refs" msgstr "Äá»c, sá»a và xóa tham chiếu má»m" @@ -14335,7 +14561,7 @@ msgid "Git for CVS users" msgstr "Git dà nh cho những ngưá»i dùng CVS" msgid "Tweaking diff output" -msgstr "Chỉnh kết xuất diff" +msgstr "Tinh chỉnh đầu ra diff" msgid "A useful minimum set of commands for Everyday Git" msgstr "Táºp hợp lệnh hữu dụng tối thiểu để dùng Git hà ng ngà y" @@ -14478,6 +14704,14 @@ msgstr "đồ-thị-chuyển-giao thiếu chunk OID lookup cần thiết hoặc msgid "commit-graph required commit data chunk missing or corrupted" msgstr "đồ-thị-chuyển-giao thiếu chunk commit data cần thiết hoặc bị há»ng" +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"vô hiệu hoá bá»™ lá»c Bloom cho đồ thị chuyển giao '%s' do tuỳ chá»n không tương " +"thÃch" + msgid "commit-graph has no base graphs chunk" msgstr "đồ thị chuyển giao không có chunk đồ thị cÆ¡ sở" @@ -14580,7 +14814,7 @@ msgid_plural "Writing out commit graph in %d passes" msgstr[0] "Äang ghi ra đồ thị các lần chuyển giao trong lần %d" msgid "unable to open commit-graph chain file" -msgstr "không thể mở táºp tin mắt xÃch đồ thị chuyển giao" +msgstr "không thể mở táºp tin chain đồ thị chuyển giao" msgid "failed to rename base commit-graph file" msgstr "gặp lá»—i khi đổi tên táºp tin đồ-thị-chuyển-giao" @@ -14604,8 +14838,15 @@ msgstr "Äang hòa trá»™n đồ-thị-chuyển-giao" msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "" -"cố gắng để ghi má»™t đồ thị các lần chuyển giao, nhưng 'core.commitGraph' bị " -"vô hiệu hóa" +"Ä‘ang thá» ghi đồ thị chuyển giao, nhưng 'core.commitGraph' bị vô hiệu hóa" + +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"Ä‘ang thá» ghi đồ thị chuyển giao, nhưng 'commitGraph.changedPathsVersion' " +"(%d) không được há»— trợ" msgid "too many commits to write graph" msgstr "có quá nhiá»u lần chuyển giao để ghi đồ thị" @@ -15765,7 +16006,7 @@ msgid "bad --word-diff argument: %s" msgstr "đối số --word-diff sai: %s" msgid "Diff output format options" -msgstr "Các tùy chá»n định dạng khi xuất các khác biệt" +msgstr "Các tùy chá»n định dạng kết quả khác biệt" msgid "generate patch" msgstr "tạo bản vá" @@ -15789,14 +16030,14 @@ msgid "machine friendly --stat" msgstr "--stat thuáºn tiện cho máy Ä‘á»c" msgid "output only the last line of --stat" -msgstr "chỉ xuất những dòng cuối cá»§a --stat" +msgstr "chỉ in ra những dòng cuối cá»§a --stat" msgid "<param1>,<param2>..." msgstr "<tham_số_1>,<tham_số_2>..." msgid "" "output the distribution of relative amount of changes for each sub-directory" -msgstr "đầu ra phân phối cá»§a số lượng thay đổi tương đối cho má»—i thư mục con" +msgstr "in ra phân phối số lượng thay đổi tương đối cho má»—i thư mục con" msgid "synonym for --dirstat=cumulative" msgstr "đồng nghÄ©a vá»›i --dirstat=cumulative" @@ -15845,7 +16086,7 @@ msgid "generate compact summary in diffstat" msgstr "tạo tổng hợp xúc tÃch trong diffstat" msgid "output a binary diff that can be applied" -msgstr "xuất ra má»™t khác biệt dạng nhị phân cái mà có thể được áp dụng" +msgstr "in ra má»™t khác biệt dạng nhị phân có thể được áp dụng" msgid "show full pre- and post-image object names on the \"index\" lines" msgstr "" @@ -15882,7 +16123,7 @@ msgid "show the given destination prefix instead of \"b/\"" msgstr "hiển thị tiá»n tố Ä‘Ãch đã cho thay cho \"b/\"" msgid "prepend an additional prefix to every line of output" -msgstr "treo và o trước má»™t tiá»n tố bổ sung cho má»—i dòng kết xuất" +msgstr "thêm và o trước má»™t tiá»n tố bổ sung cho má»—i dòng đầu ra" msgid "do not show any source or destination prefix" msgstr "đừng hiển thị bất kỳ tiá»n tố nguồn hay Ä‘Ãch" @@ -16023,7 +16264,7 @@ msgid "exit with 1 if there were differences, 0 otherwise" msgstr "thoát vá»›i mã 1 nếu không có khác biệt gì, 0 nếu ngược lại" msgid "disable all output of the program" -msgstr "tắt má»i kết xuất cá»§a chương trình" +msgstr "tắt má»i đầu ra cá»§a chương trình" msgid "allow an external diff helper to be executed" msgstr "cho phép má»™ helper xuất khác biệt ở bên ngoà i được phép thá»±c thi" @@ -16075,7 +16316,7 @@ msgid "treat <string> in -S as extended POSIX regular expression" msgstr "coi <chuá»—i> trong -S là biểu thức chÃnh quy POSIX mở rá»™ng" msgid "control the order in which files appear in the output" -msgstr "Ä‘iá»u khiển thứ tá»± xuất hiện các táºp tin trong đầu ra" +msgstr "Ä‘iá»u khiển thứ tá»± xuất hiện các táºp tin trong kết quả" msgid "<path>" msgstr "<đưá»ng-dẫn>" @@ -16084,7 +16325,7 @@ msgid "show the change in the specified path first" msgstr "hiển thị các thay đổi trong đưá»ng dẫn đã cho ở đầu" msgid "skip the output to the specified path" -msgstr "bá» qua đầu ra vá»›i đưá»ng dẫn đã cho" +msgstr "bá» qua kết quả vá»›i đưá»ng dẫn đã cho" msgid "<object-id>" msgstr "<mã-số-đối-tượng>" @@ -16284,7 +16525,7 @@ msgid "fetch-pack: unable to fork off %s" msgstr "fetch-pack: không thể rẽ nhánh %s" msgid "fetch-pack: invalid index-pack output" -msgstr "fetch-pack: kết xuất index-pack không hợp lệ" +msgstr "fetch-pack: đầu ra index-pack không hợp lệ" #, c-format msgid "%s failed" @@ -16441,19 +16682,23 @@ msgstr "" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C </đưá»ng/dẫn/>] [-c <tên>=<giá trị>]\n" " [--exec-path[=</đưá»ng/dẫn/>]] [--html-path] [--man-path] [--info-" "path]\n" -" [-p | --paginate | -P --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=</đưá»ng/dẫn/>] [--work-tree=</đưá»ng/dẫn/>] [--" -"namespace=<tên>]\n" -" [--config-env=<tên>=<envvar>] <lệnh> [<các tham số>]" +" [-p | --paginate | -P --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=</đưá»ng/" +"dẫn/>]\n" +" [--work-tree=</đưá»ng/dẫn/>] [--namespace=<tên>] [--config-" +"env=<tên>=<envvar>]\n" +" <lệnh> [<các tham số>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -16780,16 +17025,16 @@ msgid "" "The '%s' hook was ignored because it's not set as executable.\n" "You can disable this warning with `git config advice.ignoredHook false`." msgstr "" -"Móc '%s' bị bá» qua bởi vì nó không thể đặt là thá»±c thi được.\n" +"Móc '%s' bị bá» qua bởi vì nó không có cá» thá»±c thi được.\n" "Bạn có thể tắt cảnh báo nà y bằng 'git config advice.ignoredHook false'." +msgid "not a git repository" +msgstr "không phải là kho git" + #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "tham số cho --packfile phải là má»™t giá trị băm hợp lệ (có '%s')" -msgid "not a git repository" -msgstr "không phải là kho git" - #, c-format msgid "negative value for http.postBuffer; defaulting to %d" msgstr "giá trị âm cho http.postBuffer; đặt thà nh mặc định là %d" @@ -16800,6 +17045,9 @@ msgstr "Äiá»u khiển giao quyá»n không được há»— trợ vá»›i cURL < 7.2 msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "Chốt khóa công không được há»— trợ vá»›i cURL < 7.39.0" +msgid "Unknown value for http.proactiveauth" +msgstr "không hiểu giá trị cho http.proactiveauth" + msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "CURLSSLOPT_NO_REVOKE không được há»— trợ vá»›i cURL < 7.44.0" @@ -16819,6 +17067,12 @@ msgstr "" msgid "Could not set SSL backend to '%s': already set" msgstr "Không thể đặt ứng dụng chạy sau SSL cho '%s': đã đặt rồi" +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "từ chối Ä‘á»c cookie từ http.cookiefile '-'" + +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "bá» qua tuỳ chá»n http.savecookies vì http.cookiefile để trống" + #, c-format msgid "" "unable to update url base from redirection:\n" @@ -16957,13 +17211,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Không thể tạo '%s.lock': %s" +msgid "unable to create temporary object directory" +msgstr "không thể tạo thư mục đối tượng tạm thá»i" + #, c-format msgid "could not write loose object index %s" msgstr "không thể ghi táºp tin đối tượng loose %s" #, c-format -msgid "failed to write loose object index %s\n" -msgstr "ghi chỉ mục đối tượng loose %s thất bại\n" +msgid "failed to write loose object index %s" +msgstr "ghi chỉ mục đối tượng loose %s thất bại" #, c-format msgid "unexpected line: '%s'" @@ -16992,8 +17249,8 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (lần chuyển giao không hiện diện)" #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (kho chứa há»ng)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "lá»—i: gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (kho chứa há»ng)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" @@ -17022,12 +17279,13 @@ msgstr "" "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s, nhưng có nhiá»u cách giải quyết:\n" "%s" -msgid "failed to execute internal merge" -msgstr "Gặp lá»—i khi thá»±c hiện trá»™n ná»™i bá»™" +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "lá»—i: Gặp lá»—i khi thá»±c hiện trá»™n ná»™i bá»™ %s" #, c-format -msgid "unable to add %s to database" -msgstr "Không thể thêm %s và o cÆ¡ sở dữ liệu" +msgid "error: unable to add %s to database" +msgstr "lá»—i: không thể thêm %s và o cÆ¡ sở dữ liệu" #, c-format msgid "Auto-merging %s" @@ -17120,20 +17378,20 @@ msgstr "" "XUNG ÄỘT (đổi-tên/xóa): Äổi tên %s->%s trong %s, nhưng lại bị xóa trong %s." #, c-format -msgid "cannot read object %s" -msgstr "không thể Ä‘á»c đối tượng %s" +msgid "error: cannot read object %s" +msgstr "lá»—i: không thể Ä‘á»c đối tượng %s" #, c-format -msgid "object %s is not a blob" -msgstr "đối tượng %s không phải là má»™t blob" +msgid "error: object %s is not a blob" +msgstr "lá»—i: đối tượng %s không phải là má»™t blob" #, c-format msgid "" "CONFLICT (file/directory): directory in the way of %s from %s; moving it to " "%s instead." msgstr "" -"XUNG ÄỘT (táºp tin/thư mục): thư mục theo cách cá»§a %s từ %s; thay và o đó, di " -"chuyển nó đến %s." +"XUNG ÄỘT (táºp tin/thư mục): thư mục khác nằm trên %s từ %s; thay và o đó sẽ " +"di chuyển nó đến %s." #, c-format msgid "" @@ -17141,15 +17399,15 @@ msgid "" "of them so each can be recorded somewhere." msgstr "" "XUNG ÄỘT (các kiểu riêng biệt): %s có các kiểu khác nhau ở má»—i bên; đã đổi " -"tên cả hai trong số chúng để má»—i cái có thể được ghi lại ở đâu đó." +"tên cả hai để có thể ghi lại cả hai." #, c-format msgid "" "CONFLICT (distinct types): %s had different types on each side; renamed one " "of them so each can be recorded somewhere." msgstr "" -"XUNG ÄỘT (các kiểu riêng biệt): %s có các loại khác nhau ở má»—i bên; đã đổi " -"tên má»™t trong số chúng để má»—i cái có thể được ghi lại ở đâu đó." +"XUNG ÄỘT (các kiểu riêng biệt): %s có các kiểu khác nhau ở má»—i bên; đã đổi " +"tên má»™t trong số chúng để có thể ghi lại cả hai." msgid "content" msgstr "ná»™i dung" @@ -17262,6 +17520,10 @@ msgid "do not know what to do with %06o %s '%s'" msgstr "không hiểu phải là m gì vá»›i %06o %s '%s'" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (kho chứa há»ng)" + +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "Chuyển-tiếp-nhanh mô-Ä‘un-con '%s' đến lần chuyển giao sau đây:" @@ -17302,6 +17564,13 @@ msgstr "" msgid "Failed to merge submodule %s (multiple merges found)" msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con '%s' (thấy nhiá»u hòa trá»™n Ä‘a trùng)" +msgid "failed to execute internal merge" +msgstr "Gặp lá»—i khi thá»±c hiện trá»™n ná»™i bá»™" + +#, c-format +msgid "unable to add %s to database" +msgstr "Không thể thêm %s và o cÆ¡ sở dữ liệu" + #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" @@ -17405,6 +17674,14 @@ msgstr "" "XUNG ÄỘT (đổi-tên/đổi-tên): Äổi tên thư mục %s->%s trong %s. Äổi tên thư mục " "%s->%s trong %s" +#, c-format +msgid "cannot read object %s" +msgstr "không thể Ä‘á»c đối tượng %s" + +#, c-format +msgid "object %s is not a blob" +msgstr "đối tượng %s không phải là má»™t blob" + msgid "modify" msgstr "sá»a đổi" @@ -17467,7 +17744,7 @@ msgstr "gặp lá»—i khi Ä‘á»c bá»™ nhá»› đệm" #, c-format msgid "failed to add packfile '%s'" -msgstr "gặp lá»—i khi thêm táºp tin gói '%s'" +msgstr "gặp lá»—i khi thêm packfile '%s'" #, c-format msgid "failed to open pack-index '%s'" @@ -17488,9 +17765,6 @@ msgstr "không hiểu cú pháp dòng: %s" msgid "malformed line: %s" msgstr "dòng sai quy cách: %s" -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "bá» qua multi-pack-index sẵn có; tổng kiểm không khá»›p" - msgid "could not load pack" msgstr "không thể tải gói" @@ -17498,12 +17772,26 @@ msgstr "không thể tải gói" msgid "could not open index for %s" msgstr "không thể mở chỉ mục cho %s" +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "không thể liên kết '%s' và o '%s'" + +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "gặp lá»—i khi xóa multi-pack-index tại %s" + +msgid "cannot write incremental MIDX with bitmap" +msgstr "không thể ghi incremental MIDX vá»›i bitmap" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "bá» qua multi-pack-index sẵn có; tổng kiểm không khá»›p" + msgid "Adding packfiles to multi-pack-index" msgstr "Äang thêm táºp tin gói từ multi-pack-index" #, c-format msgid "unknown preferred pack: '%s'" -msgstr "không hiểu \"preferred pack\": %s" +msgstr "không hiểu preferred pack: %s" #, c-format msgid "cannot select preferred pack %s with no objects" @@ -17515,19 +17803,31 @@ msgstr "đã không thấy táºp tin gói %s để xóa" #, c-format msgid "preferred pack '%s' is expired" -msgstr "\"preferred pack\" '%s' đã hết hạn" +msgstr "preferred pack '%s' đã hết hạn" msgid "no pack files to index." msgstr "không có táºp tin gói để đánh chỉ mục." msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "từ chối ghi 'multi-pack bitmap' mà không có bất kỳ đối tượng nà o" +msgstr "từ chối ghi multi-pack bitmap mà không có bất kỳ đối tượng nà o" + +msgid "unable to create temporary MIDX layer" +msgstr "không thể tạo lá»›p MIDX tạm thá»i" msgid "could not write multi-pack bitmap" -msgstr "không thể ghi 'multi-pack bitmap'" +msgstr "không thể ghi multi-pack bitmap" + +msgid "unable to open multi-pack-index chain file" +msgstr "không thể mở táºp tin chain multi-pack-index" + +msgid "unable to rename new multi-pack-index layer" +msgstr "gặp lá»—i khi đổi tên lá»›p multi-pack-index" msgid "could not write multi-pack-index" -msgstr "không thể ghi 'multi-pack-index'" +msgstr "không thể ghi multi-pack-index" + +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "không thể hết hạn gói từ incremental multi-pack-index" msgid "Counting referenced objects" msgstr "Äang đếm các đối tượng được tham chiếu" @@ -17535,6 +17835,9 @@ msgstr "Äang đếm các đối tượng được tham chiếu" msgid "Finding and deleting unreferenced packfiles" msgstr "Äang tìm và xóa các gói không được tham chiếu" +msgid "cannot repack an incremental multi-pack-index" +msgstr "không thể repack incremental multi-pack-index" + msgid "could not start pack-objects" msgstr "không thể khởi chạy pack-objects" @@ -17591,6 +17894,27 @@ msgstr "táºp tin đồ thị multi-pack-index %s quá nhá»" msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "các tên gói multi-pack-index không đúng thứ tá»±: '%s' trước '%s'" +msgid "multi-pack-index chain file too small" +msgstr "táºp tin chain multi-pack-index quá nhá»" + +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "số pack trong base MIDX quá lá»›n: %<PRIuMAX>" + +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "số đối tượng trong base MIDX quá lá»›n: %<PRIuMAX>" + +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "multi-pack-index chain không hợp lệ: dòng '%s' không phải là mã băm" + +msgid "unable to find all multi-pack index files" +msgstr "không thể tìm thấy tất cả các táºp tin multi-pack index" + +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "vị trà đối tượng MIDX không hợp lệ. MIDX có vẻ như đã bị há»ng" + #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "pack-int-id sai: %u (%u các gói tổng)" @@ -17608,10 +17932,6 @@ msgstr "multi-pack-index lưu trữ má»™t offset 64-bÃt, nhưng off_t là quá msgid "multi-pack-index large offset out of bounds" msgstr "multi-pack-index large offset nằm ngoà i biên" -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "gặp lá»—i khi xóa multi-pack-index tại %s" - msgid "multi-pack-index file exists, but failed to parse" msgstr "đã có táºp tin multi-pack-index, nhưng gặp lá»—i khi Ä‘á»c cú pháp" @@ -17822,6 +18142,14 @@ msgid "missing mapping of %s to %s" msgstr "thiếu ánh xạ %s sang %s" #, c-format +msgid "unable to open %s" +msgstr "không thể mở %s" + +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "táºp tin '%s' và '%s' có ná»™i dung khác nhau" + +#, c-format msgid "unable to write file %s" msgstr "không thể ghi táºp tin %s" @@ -17869,7 +18197,7 @@ msgstr "deflateEnd trên đối tượng stream gặp lá»—i (%d)" #, c-format msgid "unable to create directory %s" -msgstr "tạo thư mục \"%s\" gặp lá»—i" +msgstr "tạo thư mục %s gặp lá»—i" #, c-format msgid "cannot read object for %s" @@ -17907,10 +18235,6 @@ msgid "%s is not a valid '%s' object" msgstr "%s không phải là má»™t đối tượng '%s' hợp lệ" #, c-format -msgid "unable to open %s" -msgstr "không thể mở %s" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "mã băm không khá»›p cho %s (cần %s)" @@ -18103,6 +18427,17 @@ msgstr "không thể Ä‘á»c đối tượng: '%s'" msgid "hash mismatch %s" msgstr "mã băm không khá»›p %s" +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "đối tượng trùng lặp khi ghi chỉ mục bitmap: %s" + +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "đã cố ghi lần chuyển giao không được chá»n: '%s'" + +msgid "too many pseudo-merges" +msgstr "có quá nhiá»u lần pseudo-merge" + msgid "trying to write commit not in index" msgstr "đã thá» ghi lần chuyển giao nằm ngoà i chỉ mục" @@ -18125,6 +18460,17 @@ msgstr "táºp tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bá»™ msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "táºp tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bảng tìm kiếm)" +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"táºp tin chỉ mục bitmap bị há»ng (quá ngắn để chứa đỠmục bảng pseudo-merge)" + +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "táºp tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bảng pseudo-merge)" + +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "táºp tin chỉ mục bitmap bị há»ng, bảng pseudo-merge quá ngắn" + #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "đối tượng trùng lặp trong bitmap: '%s'" @@ -18215,6 +18561,10 @@ msgid "mismatch in bitmap results" msgstr "kết quả bitmap không khá»›p" #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "chỉ mục pseudo-merge vượt ngoà i phạm vi (%<PRIu32> >= %<PRIuMAX>)" + +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "không thể tìm thấy '%s' trong gói '%s' tại vị trà %<PRIuMAX>" @@ -18579,6 +18929,9 @@ msgstr "không thể tạo tiến trình lstat: %s" msgid "unable to parse --pretty format" msgstr "không thể Ä‘á»c định dạng --pretty" +msgid "lazy fetching disabled; some objects may not be available" +msgstr "vô hiệu lazy fetching; má»™t số đối tượng sẽ không có sẵn" + msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: không thể rẽ nhánh tuyến trình con fetch" @@ -18602,6 +18955,62 @@ msgstr "object-info: cần đẩy dữ liệu lên đĩa sau các tham số" msgid "Removing duplicate objects" msgstr "Äang gỡ các đối tượng trùng lặp" +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "gặp lá»—i khi Ä‘á»c biểu thức chÃnh quy pseudo-merge cho %s: '%s'" + +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s phải không âm, dùng mặc định thay thế" + +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s nên giữa 0 và 1, dùng mặc định thay thế" + +#, c-format +msgid "%s must be positive, using default" +msgstr "%s phải dương, dùng mặc định thay thế" + +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "nhóm pseudo-merge '%s' thiếu mẫu bắt buá»™c" + +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "nhóm pseudo-merge '%s' có unstable threshold trước stable" + +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"biểu thức chÃnh quy pseudo-merge từ cấu hình có quá nhiá»u nhóm chá»n (tối " +"Ä‘a=%<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "extended pseudo-merge Ä‘á»c ngoà i biên (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "mục extended pseudo-merge quá ngắn (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"không thể tìm pseudo-merge cho lần chuyển giao %s tại vị trà %<PRIuMAX>" + +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "extended pseudo-merge lookup vượt ngoà i biên (%<PRIu32> >= %<PRIu32>)" + +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "Ä‘á»c ngoà i biên (%<PRIuMAX> >= %<PRIuMAX>)" + +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "không thể Ä‘á»c bảng extended pseudo-merge cho lần chuyển giao %s" + msgid "could not start `log`" msgstr "không thể khởi chạy `log`" @@ -18760,10 +19169,10 @@ msgid "broken index, expect %s in %s, got %s" msgstr "chỉ mục bị há»ng, cần %s trong %s, nhưng lại có %s" msgid "cannot write split index for a sparse index" -msgstr "không thể ghi chỉ mục chia tách cho \"sparse index\"" +msgstr "không thể ghi chỉ mục chia tách cho sparse index" msgid "failed to convert to a sparse-index" -msgstr "gặp lá»—i khi chuyển đổi sang \"sparse-index\"" +msgstr "gặp lá»—i khi chuyển đổi sang sparse-index" #, c-format msgid "unable to open git dir: %s" @@ -18844,7 +19253,7 @@ msgstr "" " chỉ giữ ghi chú cá»§a lần chuyển giao nà y; -c giống như -C " "nhưng\n" " mở trình biên soạn\n" -"x, exec <commit> = chạy lệnh (phần còn lại cá»§a dòng) dùng hệ vá»\n" +"x, exec <commit> = chạy lệnh (phần còn lại cá»§a dòng) dùng shell\n" "b, break = dừng tại đây (tiếp tục cải tổ sau nà y bằng 'git rebase --" "continue')\n" "d, drop <commit> = xóa bá» lần chuyển giao\n" @@ -19033,6 +19442,10 @@ msgid "expected format: %%(ahead-behind:<committish>)" msgstr "cần định dạng: %%(ahead-behind:<committish>)" #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "cần định dạng: %%(is-base:<committish>)" + +#, c-format msgid "malformed field name: %.*s" msgstr "tên trưá»ng sai quy cách: %.*s" @@ -19206,11 +19619,18 @@ msgstr "nháºt ký cho tham chiếu %s kết thúc bất ngá» trên %s" msgid "log for %s is empty" msgstr "nháºt ký cho %s trống rá»—ng" +msgid "refusing to force and skip creation of reflog" +msgstr "từ chối bá» qua việc tạo log tham chiếu" + #, c-format 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'" #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "từ chối cáºp nháºt tham chiếu ảo '%s'" + +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "update_ref bị lá»—i cho ref '%s': %s" @@ -19241,6 +19661,32 @@ msgid "could not delete references: %s" msgstr "không thể xóa bá» tham chiếu: %s" #, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "Äã hoà n thà nh thá» chạy di cư tham chiếu, kết quả tại '%s'\n" + +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "không thể xoá thư mục tạm thá»i '%s'" + +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "ydam chiếu đã di cư tại '%s'" + +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"không thể lock tham chiếu '%s': cần tham chiếu má»m tá»›i '%s': nhưng lại là " +"tham chiếu thưá»ng" + +#, c-format +msgid "cannot open directory %s" +msgstr "không thể mở thư mục %s" + +msgid "Checking references consistency" +msgstr "Äang kiểm tra tÃnh nhất quán các tham chiếu" + +#, c-format msgid "refname is dangerous: %s" msgstr "tên tham chiếu không an toà n: %s" @@ -19599,7 +20045,7 @@ msgstr "không thể tìm thấy tham chiếu máy chá»§ %s" #, c-format msgid "* Ignoring funny ref '%s' locally" -msgstr "* Äang bá» qua tham chiếu thú vị ná»™i bá»™ '%s'" +msgstr "* Äang bá» qua tham chiếu ná»™i bá»™ '%s'" #, c-format msgid "Your branch is based on '%s', but the upstream is gone.\n" @@ -19799,7 +20245,7 @@ msgstr "không thể tạo tuyến trình async: %s" #, c-format msgid "'%s' does not exist" -msgstr "\"%s\" không tồn tại" +msgstr "'%s' không tồn tại" #, c-format msgid "could not switch to '%s'" @@ -19867,12 +20313,15 @@ msgstr "chỉ siêu dữ liệu tải vá» cho nhánh mà sẽ được checkout msgid "create repository within 'src' directory" msgstr "tạo kho chứa trong thư mục 'src'" +msgid "specify if tags should be fetched during clone" +msgstr "có nên lấy vá» thẻ khi nhân bản" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <nhánh-chÃnh>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -19891,6 +20340,10 @@ msgid "could not configure remote in '%s'" msgstr "không thể cấu hình máy chá»§ trong '%s'" #, c-format +msgid "could not disable tags in '%s'" +msgstr "không thể vô hiệu thẻ trong '%s'" + +#, c-format msgid "could not configure '%s'" msgstr "không thể cấu hình '%s'" @@ -20062,9 +20515,9 @@ msgid "" "To abort and get back to the state before \"git rebase\", run \"git rebase --" "abort\"." msgstr "" -"Giải quyết vấn đỠnà y thá»§ công, hãy Ä‘anh dấu chúng đã được giải quyết bằng\n" -"hãy chạy lệnh \"git add/rm <các_táºp tin_xung_đột>\", sau đó chạy \"git " -"rebase --continue\".\n" +"Hãy giải quyết vấn đỠnà y bằng tay, đánh dấu chúng đã được giải quyết bằng\n" +"lệnh \"git add/rm <các_táºp tin_xung_đột>\", sau đó chạy \"git rebase --" +"continue\".\n" "Bạn có thể bá» qua bản vá, chạy \"git rebase --skip\".\n" "Äể huá»· bá» và quay trở lại trạng thái trước \"git rebase\", chạy \"git rebase " "--abort\"." @@ -20183,7 +20636,7 @@ msgid "" "\n" " git rebase --continue\n" msgstr "" -"bạn có các thay đổi so vá»›i trong bệ phóng trong thư mục là m việc cá»§a bạn.\n" +"bạn có các thay đổi so vá»›i trong vùng chá» trong thư mục là m việc cá»§a bạn.\n" "Nếu các thay đổi nà y là muốn squash và o lần chuyển giao kế trước, chạy:\n" "\n" " git commit --amend %s\n" @@ -20397,6 +20850,47 @@ msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s" msgstr "update-ref yêu cầu tên tham chiếu đầy đủ v.d. refs/heads/%s" #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' không nháºn đối số lần chuyển giao hoà trá»™n" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick' không cho phép dùng lần chuyển giao hoà trá»™n. Nếu như cần phát lại\n" +"lần hoà trá»™n, hà y dùng 'merge -C'." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword' không cho phép dùng lần chuyển giao hoà trá»™n. Nếu như cần phát lại\n" +"lần hoà trá»™n và sá»a ná»™i dung, hãy dùng 'merge -c'." + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'pick' không cho phép dùng lần chuyển giao hoà trá»™n. Nếu như cần phát lại\n" +"lần hoà trá»™n, hà y dùng 'merge -C', sau đó 'break' để dùng lệnh\n" +"'git commit --amend && git rebase --continue'." + +msgid "cannot squash merge commit into another commit" +msgstr "không thể squash lần chuyển giao hoà trá»™n và o lần chuyển giao khác" + +#, c-format msgid "invalid command '%.*s'" msgstr "lệnh không hợp lệ '%.*s'" @@ -20512,9 +21006,8 @@ msgstr "" msgid "cannot read HEAD" msgstr "không thể Ä‘á»c HEAD" -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "không thể sao chép '%s' sang '%s'" +msgid "could not write commit message file" +msgstr "không thể ghi táºp tin chú thÃch lần chuyển giao" #, c-format msgid "" @@ -20744,7 +21237,7 @@ msgid "Successfully rebased and updated %s.\n" msgstr "Cà i tổ và cáºp nháºt %s má»™t cách thà nh công.\n" msgid "cannot rebase: You have unstaged changes." -msgstr "không thể cải tổ: Bạn có các thay đổi chưa được đưa lên bệ phóng." +msgstr "không thể cải tổ: Bạn có các thay đổi chưa được đưa và o vùng chá»." msgid "cannot amend non-existing commit" msgstr "không thể tu sá»a lần chuyển giao không tồn tại" @@ -20774,7 +21267,7 @@ msgid "could not remove CHERRY_PICK_HEAD" msgstr "không thể xóa bá» CHERRY_PICK_HEAD" msgid "could not commit staged changes." -msgstr "không thể chuyển giao các thay đổi đã đưa lên bệ phóng." +msgstr "không thể chuyển giao các thay đổi đã đưa và o vùng chá»." #, c-format msgid "%s: can't cherry-pick a %s" @@ -20915,6 +21408,22 @@ msgstr "không thể quay lại thư mục là m việc hiện hà nh" msgid "failed to stat '%*s%s%s'" msgstr "gặp lá»—i khi stat'%*s%s%s'" +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' không phải đưá»ng dẫn tuyệt đối" + +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"kho lưu trữ '%s' thuá»™c sở hữu cá»§a ngưá»i khác\n" +"%sÄể thêm ngoại lệ cho thư mục nà y, hãy gá»i:\n" +"\n" +"\tgit config --global --add safe.directory %s" + msgid "Unable to read current working directory" msgstr "Không thể Ä‘á»c thư mục là m việc hiện hà nh" @@ -20937,18 +21446,6 @@ msgstr "" "được đặt)." #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"kho lưu trữ '%s' thuá»™c sở hữu cá»§a ngưá»i khác\n" -"%sÄể thêm ngoại lệ cho thư mục nà y, hãy gá»i:\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "không thể dùng kho chứa bare '%s' (safe.bareRepository là '%s')" @@ -21249,6 +21746,15 @@ msgid "submodule git dir '%s' is inside git dir '%.*s'" msgstr "thư mục git mô Ä‘un con '%s' là bên trong git DIR '%.*s'" #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"cần '%.*s' trong đưá»ng dẫn tá»›i mô-Ä‘un-con '%s' không phải là liên kết má»m" + +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "cần đưá»ng dẫn tá»›i mô-Ä‘un-con '%s' không phải là liên kết má»m" + +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" @@ -21287,10 +21793,6 @@ msgstr "gặp lá»—i khi lstat '%s'" msgid "no remote configured to get bundle URIs from" msgstr "không có máy chá»§ để lấy URI bundle" -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "máy chá»§ '%s' không có cấu hình URL" - msgid "could not get the bundle-uri list" msgstr "không thể lấy vá» danh sách bundle-uri" @@ -21372,9 +21874,27 @@ msgstr "thẻ bà i" msgid "command token to send to the server" msgstr "thẻ bà i lệnh để gá»i lên cho máy chá»§" +msgid "unit-test [<options>]" +msgstr "unit-test [<các tùy chá»n>]" + +msgid "immediately exit upon the first failed test" +msgstr "thoát ngay khi gặp test thất bại" + +msgid "suite[::test]" +msgstr "suite[::test]" + +msgid "run only test suite or individual test <suite[::test]>" +msgstr "chạy riêng test suite hoặc test <suite[::test]>" + +msgid "suite" +msgstr "suite" + +msgid "exclude test suite <suite>" +msgstr "loại trừ test suite <suite>" + #, c-format msgid "running trailer command '%s' failed" -msgstr "chạy lệnh kéo theo '%s' gặp lá»—i" +msgstr "chạy lệnh trailer '%s' gặp lá»—i" #, c-format msgid "unknown value '%s' for key '%s'" @@ -21382,7 +21902,7 @@ msgstr "không hiểu giá trị '%s' cho khóa '%s'" #, c-format msgid "empty trailer token in trailer '%.*s'" -msgstr "thẻ thừa trống rá»—ng trong phần thừa '%.*s'" +msgstr "thẻ trailer trống rá»—ng trong phần trailer '%.*s'" msgid "full write to remote helper failed" msgstr "ghi đầy đủ lên helper máy chá»§ gặp lá»—i" @@ -21915,7 +22435,7 @@ msgid "error: unable to format message: %s\n" msgstr "lá»—i: không thể định dạng thông Ä‘iệp: %s\n" msgid "usage: " -msgstr "cách dùng: %s" +msgstr "cách dùng: " msgid "fatal: " msgstr "lá»—i nghiêm trá»ng: " @@ -22033,7 +22553,7 @@ msgid "Unmerged paths:" msgstr "Những đưá»ng dẫn chưa được hòa trá»™n:" msgid " (use \"git restore --staged <file>...\" to unstage)" -msgstr " (dùng \"git restore --staged <táºp-tin>...\" để bá» ra khá»i bệ phóng)" +msgstr " (dùng \"git restore --staged <táºp-tin>...\" để bá» ra khá»i vùng chá»)" #, c-format msgid " (use \"git restore --source=%s --staged <file>...\" to unstage)" @@ -22042,7 +22562,7 @@ msgstr "" "phóng)" msgid " (use \"git rm --cached <file>...\" to unstage)" -msgstr " (dùng \"git rm --cached <táºp-tin>...\" để bá» ra khá»i bệ phóng)" +msgstr " (dùng \"git rm --cached <táºp-tin>...\" để bá» ra khá»i vùng chá»)" msgid " (use \"git add <file>...\" to mark resolution)" msgstr " (dùng \"git add <táºp-tin>...\" để đánh dấu là muốn thêm)" @@ -22057,7 +22577,7 @@ msgid "Changes to be committed:" msgstr "Những thay đổi sẽ được chuyển giao:" msgid "Changes not staged for commit:" -msgstr "Các thay đổi chưa được đặt lên bệ phóng để chuyển giao:" +msgstr "Các thay đổi chưa được đặt và o vùng chỠđể chuyển giao:" msgid " (use \"git add <file>...\" to update what will be committed)" msgstr "" @@ -22465,7 +22985,7 @@ msgstr "đứng trước " #. TRANSLATORS: the action is e.g. "pull with rebase" #, c-format msgid "cannot %s: You have unstaged changes." -msgstr "không thể %s: Bạn có các thay đổi chưa được đưa lên bệ phóng." +msgstr "không thể %s: Bạn có các thay đổi chưa được đưa và o vùng chá»." msgid "additionally, your index contains uncommitted changes." msgstr "ngoà i ra, chỉ mục cá»§a bạn có chứa các thay đổi chưa được chuyển giao." @@ -22526,11 +23046,11 @@ msgstr "" msgid "Cannot rewrite branches: You have unstaged changes." msgstr "" -"Không thể ghi lại các nhánh: Bạn có các thay đổi chưa được đưa lên bệ phóng." +"Không thể ghi lại các nhánh: Bạn có các thay đổi chưa được đưa và o vùng chá»." #, sh-format msgid "Cannot $action: You have unstaged changes." -msgstr "Không thể $action: Bạn có các thay đổi chưa được đưa lên bệ phóng." +msgstr "Không thể $action: Bạn có các thay đổi chưa được đưa và o vùng chá»." #, sh-format msgid "Cannot $action: Your index contains uncommitted changes." @@ -22572,6 +23092,9 @@ msgstr "'%s.final' chứa emal đã soạn thảo.\n" msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases không tương thÃch vá»›i các tùy chá»n khác\n" +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases và --translate-aliases không tương thÃch vá»›i nhau\n" + msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -22751,7 +23274,7 @@ msgstr "" #. translation. The program will only accept English input #. at this point. msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): " -msgstr "Gá»i email nà y chứ? ([y]có|[n]không|[e]sá»a|[q]thoát|[a]tất): " +msgstr "Gá»i email nà y chứ? ([y]có|[n]không|[e]sá»a|[q]thoát|[a]tất cả): " msgid "Send this email reply required" msgstr "Hãy trả lá»i yêu cầu gá»i email" @@ -22776,24 +23299,24 @@ msgid "Failed to send %s\n" msgstr "Gặp lá»—i khi gá»i %s\n" #, perl-format -msgid "Dry-Sent %s\n" -msgstr "Thá» gá»i %s\n" +msgid "Dry-Sent %s" +msgstr "Thá» gá»i %s" #, perl-format -msgid "Sent %s\n" -msgstr "Gá»i %s\n" +msgid "Sent %s" +msgstr "Gá»i %s" -msgid "Dry-OK. Log says:\n" -msgstr "Thá» gá»i OK. Nháºt ký ghi lại:\n" +msgid "Dry-OK. Log says:" +msgstr "Thá» gá»i OK. Nháºt ký ghi lại:" -msgid "OK. Log says:\n" -msgstr "OK. Nháºt ký ghi lại:\n" +msgid "OK. Log says:" +msgstr "OK. Nháºt ký ghi lại:" msgid "Result: " msgstr "Kết quả: " -msgid "Result: OK\n" -msgstr "Kết quả: OK\n" +msgid "Result: OK" +msgstr "Kết quả: OK" #, perl-format msgid "can't open file %s" diff --git a/po/zh_CN.po b/po/zh_CN.po index 4838c19b0b..55d2aee627 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -154,8 +154,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-28 19:59+0800\n" -"PO-Revision-Date: 2024-04-28 20:31+0800\n" +"POT-Creation-Date: 2024-10-05 03:31+0800\n" +"PO-Revision-Date: 2024-10-05 03:32+0800\n" "Last-Translator: Teng Long <dyroneteng@gmail.com>\n" "Language-Team: GitHub <https://github.com/dyrone/git/>\n" "Language: zh_CN\n" @@ -252,12 +252,12 @@ msgstr[1] "å¢žåŠ äº† %d 个路径\n" msgid "ignoring unmerged: %s" msgstr "忽略未åˆå…¥çš„:%s" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "Only binary files changed.\n" msgstr "åªæœ‰äºŒè¿›åˆ¶æ–‡ä»¶è¢«ä¿®æ”¹ã€‚\n" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "No changes.\n" msgstr "没有修改。\n" @@ -784,7 +784,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - ç»´æŒè¯¥å—未决状æ€ï¼ŒæŸ¥çœ‹ä¸‹ä¸€ä¸ªæœªå†³å—\n" @@ -795,10 +795,15 @@ msgstr "" "/ - 查找和给定æ£åˆ™è¡¨è¾¾å¼åŒ¹é…çš„å—\n" "s - 拆分当å‰å—为更å°çš„å—\n" "e - 手动编辑当å‰å—\n" -"p - 显示当å‰å—\n" +"p - 显示当å‰å—, 'P' 使用分页器\n" "? - 显示帮助\n" #: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "é¢„æœŸåªæœ‰ä¸€ä¸ªå—æ¯ï¼Œå¾—到 '%s'" + +#: add-patch.c msgid "No previous hunk" msgstr "没有å‰ä¸€ä¸ªå—" @@ -861,9 +866,22 @@ msgid "Sorry, cannot edit this hunk" msgstr "对ä¸èµ·ï¼Œä¸èƒ½ç¼–辑这个å—" #: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "未知命令 '%s'(使用 '?' 寻求帮助)" + +#: add-patch.c msgid "'git apply' failed" msgstr "'git apply' 失败" +#: add-patch.c +msgid "No changes." +msgstr "没有修改。" + +#: add-patch.c +msgid "Only binary files changed." +msgstr "åªæœ‰äºŒè¿›åˆ¶æ–‡ä»¶è¢«ä¿®æ”¹ã€‚" + #: advice.c #, c-format msgid "" @@ -1036,7 +1054,7 @@ msgid "unclosed quote" msgstr "未关é—的引å·" #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c -#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c msgid "too many arguments" msgstr "å¤ªå¤šå‚æ•°" @@ -1595,6 +1613,18 @@ msgstr "还应用æ¤è¡¥ä¸ï¼ˆä¸Ž --stat/--summary/--check é€‰é¡¹åŒæ—¶ä½¿ç”¨ï¼‰" msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "å°è¯•三路åˆå¹¶ï¼Œå¦‚果失败则回è½è‡³æ£å¸¸è¡¥ä¸æ¨¡å¼" +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "如果冲çªï¼Œä½¿ç”¨æˆ‘们的版本" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "如果冲çªï¼Œä½¿ç”¨ä»–们的版本" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "如果冲çªï¼Œä½¿ç”¨è”åˆç‰ˆæœ¬" + #: apply.c msgid "build a temporary index based on embedded index information" msgstr "创建一个临时索引基于嵌入的索引信æ¯" @@ -1656,6 +1686,10 @@ msgstr "为所有文件å剿·»åŠ <æ ¹ç›®å½•>" msgid "don't return error for empty patches" msgstr "对空的补ä¸ä¸è¿”回错误" +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "--oursã€--theirs å’Œ --union éœ€è¦ --3way" + #: archive-tar.c archive-zip.c #, c-format msgid "cannot stream blob %s" @@ -1744,6 +1778,10 @@ msgstr "䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„对象å:%s" msgid "not a tree object: %s" msgstr "䏿˜¯ä¸€ä¸ªæ ‘对象:%s" +#: archive.c builtin/clone.c +msgid "unable to checkout working tree" +msgstr "ä¸èƒ½æ£€å‡ºå·¥ä½œåŒº" + #: archive.c #, c-format msgid "File not found: %s" @@ -1860,7 +1898,7 @@ msgstr "选项 '%s' éœ€è¦ '%s'" msgid "Unexpected option --output" msgstr "æœªçŸ¥å‚æ•° --output" -#: archive.c +#: archive.c t/unit-tests/unit-test.c #, c-format msgid "extra command line parameter '%s'" msgstr "é¢å¤–çš„å‘½ä»¤è¡Œå‚æ•°ï¼š'%s'" @@ -1918,6 +1956,10 @@ msgid "ignoring overly large gitattributes blob '%s'" msgstr "忽略过大的 gitattributes æ•°æ®å¯¹è±¡ '%s'" #: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "æ— æ³•åœ¨æ²¡æœ‰å˜å‚¨åº“的情况下使用 --attr-source 或 GIT_ATTR_SOURCE" + +#: attr.c msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "错误的 --attr-source 或 GIT_ATTR_SOURCE" @@ -1927,7 +1969,7 @@ msgid "unable to stat '%s'" msgstr "æ— æ³•å¯¹ %s 执行 stat" #: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c -#: builtin/pack-objects.c combine-diff.c rerere.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c #, c-format msgid "unable to read %s" msgstr "ä¸èƒ½è¯» %s" @@ -2064,7 +2106,7 @@ msgstr "--contents å’Œ --reverse ä¸èƒ½æ··ç”¨ã€‚" msgid "--reverse and --first-parent together require specified latest commit" msgstr "--reverse å’Œ --first-parent å…±ç”¨ï¼Œéœ€è¦æŒ‡å®šæœ€æ–°çš„æäº¤" -#: blame.c builtin/commit.c builtin/log.c builtin/merge.c +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c #: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c #: remote.c sequencer.c submodule.c msgid "revision walk setup failed" @@ -2278,14 +2320,6 @@ msgid "Unstaged changes after refreshing the index:" msgstr "刷新索引之åŽå°šæœªè¢«æš‚å˜çš„å˜æ›´ï¼š" #: builtin/add.c -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"设置 add.interactive.useBuiltin å·²ç»è¢«ç§»é™¤ï¼\n" -"查看 'git help config' ä¸çš„相关æ¡ç›®ä»¥èŽ·å–æ›´å¤šä¿¡æ¯ã€‚" - -#: builtin/add.c msgid "could not read the index" msgstr "ä¸èƒ½è¯»å–索引" @@ -2319,7 +2353,7 @@ msgstr "æ¼”ä¹ " #: builtin/add.c builtin/check-ignore.c builtin/commit.c #: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c -#: builtin/read-tree.c +#: builtin/read-tree.c builtin/refs.c msgid "be verbose" msgstr "冗长输出" @@ -2720,7 +2754,7 @@ msgid "" "Not rewinding to ORIG_HEAD" msgstr "您好åƒåœ¨ä¸Šä¸€æ¬¡ 'am' 失败åŽç§»åŠ¨äº† HEAD。未回退至 ORIG_HEAD" -#: builtin/am.c builtin/bisect.c worktree.c +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c #, c-format msgid "failed to read '%s'" msgstr "æ— æ³•è¯»å– '%s'" @@ -2798,8 +2832,8 @@ msgstr "n" #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c -#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c -#: builtin/verify-tag.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c msgid "format" msgstr "æ ¼å¼" @@ -2836,6 +2870,10 @@ msgid "show the patch being applied" msgstr "显示æ£åœ¨åº”用的补ä¸" #: builtin/am.c +msgid "try to apply current patch again" +msgstr "å°è¯•冿¬¡åº”用当å‰è¡¥ä¸" + +#: builtin/am.c msgid "record the empty patch as an empty commit" msgstr "把空补ä¸è®°å½•为空æäº¤" @@ -2907,10 +2945,6 @@ msgid "could not redirect output" msgstr "ä¸èƒ½é‡å®šå‘输出" #: builtin/archive.c -msgid "git archive: Remote with no URL" -msgstr "git archive:未æä¾›è¿œç¨‹ URL" - -#: builtin/archive.c msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archive:期望是 ACK/NAK,å´å¾—到 flush 包" @@ -3094,10 +3128,6 @@ msgstr "" "支æŒçš„选项有:--term-good|--term-old å’Œ --term-bad|--term-new。" #: builtin/bisect.c -msgid "revision walk setup failed\n" -msgstr "版本é历设置失败\n" - -#: builtin/bisect.c #, c-format msgid "could not open '%s' for appending" msgstr "æ— æ³•æ‰“å¼€ '%s' è¿›è¡Œè¿½åŠ " @@ -4024,6 +4054,10 @@ msgstr "需è¦ä¸€ä¸ªä»“库æ¥åˆ›å»ºå½’档包。" msgid "do not show bundle details" msgstr "䏿˜¾ç¤ºå½’档包的细节" +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "需è¦ä¸€ä¸ªä»“åº“æ¥æ ¡éªŒä¸€ä¸ªå½’档包" + #: builtin/bundle.c #, c-format msgid "%s is okay\n" @@ -4319,9 +4353,16 @@ msgid "also read contacts from stdin" msgstr "è¿˜ä»Žæ ‡å‡†è¾“å…¥è¯»å–è”系地å€" #: builtin/check-mailmap.c -#, c-format -msgid "unable to parse contact: %s" -msgstr "ä¸èƒ½è§£æžè”系地å€ï¼š%s" +msgid "read additional mailmap entries from file" +msgstr "从文件ä¸è¯»å–é™„åŠ é‚®ä»¶æ˜ å°„æ¡ç›®" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "æ•°æ®å¯¹è±¡" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "从数æ®å¯¹è±¡ä¸è¯»å–é™„åŠ é‚®ä»¶æ˜ å°„æ¡ç›®" #: builtin/check-mailmap.c msgid "no contacts specified" @@ -4741,6 +4782,11 @@ msgstr "'%s' ä¸èƒ½å’Œåˆ‡æ¢åˆ†æ”¯åŒæ—¶ä½¿ç”¨" #: builtin/checkout.c #, c-format +msgid "'%s' needs the paths to check out" +msgstr "'%s' 需è¦è·¯å¾„进行检出" + +#: builtin/checkout.c +#, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s' ä¸èƒ½å’Œ '%s' åŒæ—¶ä½¿ç”¨" @@ -5064,9 +5110,9 @@ msgstr "äº¤äº’å¼æ¸…除" msgid "remove whole directories" msgstr "åˆ é™¤æ•´ä¸ªç›®å½•" -#: builtin/clean.c builtin/describe.c builtin/grep.c builtin/log.c -#: builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c builtin/show-ref.c -#: ref-filter.h +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h msgid "pattern" msgstr "模å¼" @@ -5205,7 +5251,7 @@ msgstr "git目录" msgid "separate git dir from working tree" msgstr "git目录和工作区分离" -#: builtin/clone.c builtin/init-db.c +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c msgid "specify the reference format to use" msgstr "指定è¦ä½¿ç”¨çš„å¼•ç”¨æ ¼å¼" @@ -5284,6 +5330,16 @@ 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'" @@ -5292,7 +5348,7 @@ msgstr "æ— æ³•åˆ›å»ºé“¾æŽ¥ '%s'" msgid "failed to copy file to '%s'" msgstr "æ— æ³•æ‹·è´æ–‡ä»¶è‡³ '%s'" -#: builtin/clone.c +#: builtin/clone.c refs/files-backend.c #, c-format msgid "failed to iterate over '%s'" msgstr "æ— æ³•åœ¨ '%s' 上è¿ä»£" @@ -5335,10 +5391,6 @@ 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 "æ— æ³•å°†å‚æ•°å†™å…¥é…置文件" @@ -5358,7 +5410,8 @@ msgstr "å¤ªå¤šå‚æ•°ã€‚" msgid "You must specify a repository to clone." msgstr "您必须指定一个仓库æ¥å…‹éš†ã€‚" -#: builtin/clone.c builtin/init-db.c setup.c +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c #, c-format msgid "unknown ref storage format '%s'" msgstr "未知的引用å˜å‚¨æ ¼å¼ '%s'" @@ -5696,7 +5749,7 @@ msgstr "git commit-treeï¼šæ— æ³•è¯»å–" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -5706,7 +5759,7 @@ msgid "" msgstr "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u<模å¼>] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <æäº¤> | --fixup [(amend|" -"reword):]<æäº¤>)]\n" +"reword):]<æäº¤>]\n" " [-F <文件> | -m <消æ¯>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<作者>]\n" " [--date=<日期>] [--cleanup=<模å¼>] [--[no-]status]\n" @@ -5967,7 +6020,7 @@ msgstr "%sæäº¤è€…:%.*s <%.*s>" msgid "Cannot read index" msgstr "æ— æ³•è¯»å–索引" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "unable to pass trailers to --trailers" msgstr "æ— æ³•å°†å°¾æ³¨ä¼ é€’ç»™ --trailers" @@ -6177,11 +6230,11 @@ msgstr "ä½¿ç”¨è‡ªåŠ¨æŒ¤åŽ‹æ ¼å¼çš„æäº¤è¯´æ˜Žç”¨ä»¥æŒ¤åŽ‹è‡³æŒ‡å®šçš„æäº¤" msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "现在将该æäº¤çš„作者改为我(和 -C/-c/--amend 傿•°å…±ç”¨ï¼‰" -#: builtin/commit.c builtin/interpret-trailers.c +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c msgid "trailer" msgstr "尾注" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "add custom trailer(s)" msgstr "æ·»åŠ è‡ªå®šä¹‰å°¾æ³¨" @@ -6293,17 +6346,65 @@ msgstr "" "ç£ç›˜é…é¢å·²è€—å°½ï¼Œç„¶åŽæ‰§è¡Œ \"git restore --staged :/\" æ¢å¤ã€‚" #: builtin/config.c -msgid "git config [<options>]" -msgstr "git config [<选项>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<文件选项>] [<显示选项>] [--includes]" #: builtin/config.c -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "未能识别的 --type 傿•°ï¼Œ%s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<文件选项>] [<显示选项>] [--includes] [--all] [--regexp] [--" +"value=<值>] [--fixed-value] [--default=<默认值>] <åç§°>" #: builtin/config.c -msgid "only one type at a time" -msgstr "一次åªèƒ½ä¸€ä¸ªç±»åž‹" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<文件选项>] [--type=<类型>] [--all] [--value=<值>] [--fixed-" +"value] <åç§°> <值>" + +#: builtin/config.c +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<文件选项>] [--all] [--value=<值>] [--fixed-value] <åç§°> <" +"值>" + +#: builtin/config.c +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<文件选项>] <æ—§åç§°> <æ–°åç§°>" + +#: builtin/config.c +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<文件选项>] <åç§°>" + +#: builtin/config.c +msgid "git config edit [<file-option>]" +msgstr "git config edit [<文件选项>]" + +#: builtin/config.c +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<文件选项>] --get-colorbool <åç§°> [<æ ‡å‡†è¾“å‡ºä¸ºtty>]" + +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<文件选项>] [<显示选项>] [--includes] [--all] [--regexp=<æ£åˆ™" +"表达å¼>] [--value=<值>] [--fixed-value] [--default=<默认值>] <åç§°>" + +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<文件选项>] [--type=<类型>] [--comment=<消æ¯>] [--all] [--" +"value=<值>] [--fixed-value] <åç§°> <值>" #: builtin/config.c msgid "Config file location" @@ -6338,70 +6439,6 @@ msgid "read config from given blob object" msgstr "从给定的数æ®å¯¹è±¡è¯»å–é…ç½®" #: builtin/config.c -msgid "Action" -msgstr "æ“作" - -#: builtin/config.c -msgid "get value: name [value-pattern]" -msgstr "获å–值:åç§° [值模å¼]" - -#: builtin/config.c -msgid "get all values: key [value-pattern]" -msgstr "获得所有的值:键 [值模å¼]" - -#: builtin/config.c -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "æ ¹æ®æ£åˆ™è¡¨è¾¾å¼èŽ·å¾—å€¼ï¼šåç§°æ£åˆ™ [值模å¼]" - -#: builtin/config.c -msgid "get value specific for the URL: section[.var] URL" -msgstr "获得 URL å–值:section[.var] URL" - -#: builtin/config.c -msgid "replace all matching variables: name value [value-pattern]" -msgstr "æ›¿æ¢æ‰€æœ‰åŒ¹é…çš„å˜é‡ï¼šåç§° 值 [值模å¼]" - -#: builtin/config.c -msgid "add a new variable: name value" -msgstr "æ·»åŠ ä¸€ä¸ªæ–°çš„å˜é‡ï¼šåç§° 值" - -#: builtin/config.c -msgid "remove a variable: name [value-pattern]" -msgstr "åˆ é™¤ä¸€ä¸ªå˜é‡ï¼šåç§° [值模å¼]" - -#: builtin/config.c -msgid "remove all matches: name [value-pattern]" -msgstr "åˆ é™¤æ‰€æœ‰åŒ¹é…项:åç§° [值模å¼]" - -#: builtin/config.c -msgid "rename section: old-name new-name" -msgstr "é‡å‘½åå°èŠ‚ï¼šold-name new-name" - -#: builtin/config.c -msgid "remove a section: name" -msgstr "åˆ é™¤ä¸€ä¸ªå°èŠ‚ï¼šname" - -#: builtin/config.c -msgid "list all" -msgstr "列出所有" - -#: builtin/config.c -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "在比较值与 '值模å¼' 时,使用å—符串å—颿¯”较" - -#: builtin/config.c -msgid "open an editor" -msgstr "打开一个编辑器" - -#: builtin/config.c -msgid "find the color configured: slot [default]" -msgstr "获得é…置的颜色:é…ç½® [默认]" - -#: builtin/config.c -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "获得颜色设置:é…ç½® [stdout-is-tty]" - -#: builtin/config.c msgid "Type" msgstr "类型" @@ -6438,8 +6475,8 @@ msgid "value is an expiry date" msgstr "值是一个到期日期" #: builtin/config.c -msgid "Other" -msgstr "其它" +msgid "Display options" +msgstr "显示选项" #: builtin/config.c msgid "terminate values with NUL byte" @@ -6450,10 +6487,6 @@ msgid "show variable names only" msgstr "åªæ˜¾ç¤ºå˜é‡å" #: builtin/config.c -msgid "respect include directives on lookup" -msgstr "查询时å‚ç…§ include 指令递归查找" - -#: builtin/config.c msgid "show origin of config (file, standard input, blob, command line)" msgstr "显示é…ç½®çš„æ¥æºï¼ˆæ–‡ä»¶ã€æ ‡å‡†è¾“å…¥ã€æ•°æ®å¯¹è±¡ï¼Œæˆ–命令行)" @@ -6462,16 +6495,17 @@ msgid "show scope of config (worktree, local, global, system, command)" msgstr "显示é…ç½®çš„ä½œç”¨åŸŸï¼ˆå·¥ä½œåŒºã€æœ¬åœ°ã€å…¨å±€ã€ç³»ç»Ÿã€å‘½ä»¤ï¼‰" #: builtin/config.c -msgid "value" -msgstr "å–值" +msgid "show config keys in addition to their values" +msgstr "显示é…置键åŠå…¶å€¼" #: builtin/config.c -msgid "with --get, use default value when missing entry" -msgstr "使用 --get 傿•°ï¼Œå½“缺少设置时使用默认值" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "未能识别的 --type 傿•°ï¼Œ%s" #: builtin/config.c -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "人类å¯è¯»çš„æ³¨é‡Šå—符串(# å°†æ ¹æ®éœ€è¦æ·»åŠ åˆ°å‰é¢ï¼‰" +msgid "only one type at a time" +msgstr "一次åªèƒ½ä¸€ä¸ªç±»åž‹" #: builtin/config.c #, c-format @@ -6564,56 +6598,93 @@ msgstr "" "详情请阅读“git help worktreeâ€çš„“CONFIGURATION FILEâ€å°èŠ‚" #: builtin/config.c -msgid "--get-color and variable type are incoherent" -msgstr "--get-color å’Œå˜é‡ç±»åž‹ä¸å…¼å®¹" +msgid "Other" +msgstr "其它" #: builtin/config.c -msgid "only one action at a time" -msgstr "一次åªèƒ½æœ‰ä¸€ä¸ªåŠ¨ä½œ" +msgid "respect include directives on lookup" +msgstr "查询时å‚ç…§ include 指令递归查找" #: builtin/config.c -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only 仅适用于 --list 或 --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "æ— æ³•è¯»å–é…置文件 '%s'" #: builtin/config.c -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "--show-origin 仅适用于 --getã€--get-allã€--get-regexp å’Œ --list" +msgid "error processing config file(s)" +msgstr "处ç†é…置文件出错" #: builtin/config.c -msgid "--default is only applicable to --get" -msgstr "--default 仅适用于 --get" +msgid "Filter options" +msgstr "过滤选项" #: builtin/config.c -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment 仅适用于 add/set/replace æ“作" +msgid "return all values for multi-valued config options" +msgstr "返回多值é…置选项的所有值" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "å°†å称解释为æ£åˆ™è¡¨è¾¾å¼" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "显示值与模å¼åŒ¹é…çš„é…ç½®" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" +msgstr "在将值与值模å¼è¿›è¡Œæ¯”较时使用å—ç¬¦ä¸²ç›¸ç‰æ€§" + +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "显示与给定 URL 匹é…çš„é…ç½®" + +#: builtin/config.c +msgid "value" +msgstr "值" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "缺少æ¡ç›®æ—¶ä½¿ç”¨é»˜è®¤å€¼" #: builtin/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value 仅适用于有 '值模å¼'" #: builtin/config.c -#, c-format -msgid "unable to read config file '%s'" -msgstr "æ— æ³•è¯»å–é…置文件 '%s'" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= ä¸èƒ½ä¸Ž --all 或 --url= 一起使用" #: builtin/config.c -msgid "error processing config file(s)" -msgstr "处ç†é…置文件出错" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= ä¸èƒ½ä¸Ž --allã€--regexp 或 --value 一起使用" #: builtin/config.c -msgid "editing stdin is not supported" -msgstr "䏿”¯æŒç¼–è¾‘æ ‡å‡†è¾“å…¥" +msgid "Filter" +msgstr "过滤器" #: builtin/config.c -msgid "editing blobs is not supported" -msgstr "䏿”¯æŒç¼–辑数æ®å¯¹è±¡" +msgid "replace multi-valued config option with new value" +msgstr "将多值é…置选项替æ¢ä¸ºæ–°å€¼" #: builtin/config.c -#, c-format -msgid "cannot create configuration file %s" -msgstr "ä¸èƒ½åˆ›å»ºé…置文件 %s" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "人类å¯è¯»çš„æ³¨é‡Šå—符串(# å°†æ ¹æ®éœ€è¦æ·»åŠ åˆ°å‰é¢ï¼‰" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "æ·»åŠ æ–°è¡Œè€Œä¸æ›´æ”¹ä»»ä½•现有值" + +#: builtin/config.c +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value åªèƒ½ä¸Ž --value=<模å¼> é…åˆä½¿ç”¨" + +#: builtin/config.c +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append ä¸èƒ½ä¸Ž --value=<模å¼> 一起使用" #: builtin/config.c #, c-format @@ -6629,6 +6700,109 @@ msgstr "" msgid "no such section: %s" msgstr "æ— æ¤å°èŠ‚ï¼š%s" +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "䏿”¯æŒç¼–è¾‘æ ‡å‡†è¾“å…¥" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "䏿”¯æŒç¼–辑数æ®å¯¹è±¡" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "ä¸èƒ½åˆ›å»ºé…置文件 %s" + +#: builtin/config.c +msgid "Action" +msgstr "æ“作" + +#: builtin/config.c +msgid "get value: name [<value-pattern>]" +msgstr "获å–值:name [<值模å¼>]" + +#: builtin/config.c +msgid "get all values: key [<value-pattern>]" +msgstr "èŽ·å–æ‰€æœ‰å€¼ï¼škey [<值模å¼>]" + +#: builtin/config.c +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "èŽ·å–æ£åˆ™è¡¨è¾¾å¼çš„值:name-regex [<值模å¼>]" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "获得 URL å–值:section[.var] URL" + +#: builtin/config.c +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "æ›¿æ¢æ‰€æœ‰åŒ¹é…çš„å˜é‡ï¼šname value [<值模å¼>]" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "æ·»åŠ ä¸€ä¸ªæ–°çš„å˜é‡ï¼šåç§° 值" + +#: builtin/config.c +msgid "remove a variable: name [<value-pattern>]" +msgstr "åˆ é™¤ä¸€ä¸ªå˜é‡ï¼šåç§° [<值模å¼>]" + +#: builtin/config.c +msgid "remove all matches: name [<value-pattern>]" +msgstr "åˆ é™¤æ‰€æœ‰åŒ¹é…项:åç§° [<值模å¼>]" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "é‡å‘½åå°èŠ‚ï¼šold-name new-name" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "åˆ é™¤ä¸€ä¸ªå°èŠ‚ï¼šname" + +#: builtin/config.c +msgid "list all" +msgstr "列出所有" + +#: builtin/config.c +msgid "open an editor" +msgstr "打开编辑器" + +#: builtin/config.c +msgid "find the color configured: slot [<default>]" +msgstr "找到é…置的颜色:slot [<默认>]" + +#: builtin/config.c +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "找到颜色设置:slot [<stdout-is-tty>]" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "使用 --get 傿•°ï¼Œå½“缺少设置时使用默认值" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "--get-color å’Œå˜é‡ç±»åž‹ä¸å…¼å®¹" + +#: builtin/config.c +msgid "no action specified" +msgstr "未指定任何æ“作" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only 仅适用于 --list 或 --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "--show-origin 仅适用于 --getã€--get-allã€--get-regexp å’Œ --list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "--default 仅适用于 --get" + +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment 仅适用于 add/set/replace æ“作" + #: builtin/count-objects.c msgid "print sizes in human readable format" msgstr "以用户å¯è¯»çš„æ ¼å¼æ˜¾ç¤ºå¤§å°" @@ -7232,8 +7406,8 @@ msgstr "" #: builtin/fetch.c #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s 未å‘逿‰€æœ‰å¿…需的对象\n" +msgid "%s did not send all necessary objects" +msgstr "%s 未å‘逿‰€æœ‰å¿…需的对象" #: builtin/fetch.c #, c-format @@ -7281,8 +7455,8 @@ msgstr "选项 \"%s\" 的值 \"%s\" 对于 %s æ˜¯æ— æ•ˆçš„" #: builtin/fetch.c #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "选项 \"%s\" 为 %s 所忽略\n" +msgid "option \"%s\" is ignored for %s" +msgstr "选项 \"%s\" 为 %s 所忽略" #: builtin/fetch.c object-file.c #, c-format @@ -7655,6 +7829,10 @@ msgid "config key storing a list of repository paths" msgstr "å˜å‚¨ç€ä»“库路径列表的é…置项键å" #: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "å³ä½¿å˜å‚¨åº“ä¸çš„命令失败,ä»ç»§ç»æ‰§è¡Œ" + +#: builtin/for-each-repo.c msgid "missing --config=<config>" msgstr "缺少 --config=<é…ç½®>" @@ -8121,6 +8299,10 @@ msgid "enable auto-gc mode" msgstr "å¯ç”¨è‡ªåŠ¨åžƒåœ¾å›žæ”¶æ¨¡å¼" #: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "在åŽå°è¿›è¡Œåžƒåœ¾å›žæ”¶" + +#: builtin/gc.c msgid "force running gc even if there may be another gc running" msgstr "强制执行 gc å³ä½¿å¦å¤–一个 gc æ£åœ¨æ‰§è¡Œ" @@ -8238,6 +8420,10 @@ msgid "run tasks based on the state of the repository" msgstr "åŸºäºŽä»“åº“çŠ¶æ€æ¥è¿è¡Œä»»åŠ¡" #: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "在åŽå°æ‰§è¡Œè¿ç»´" + +#: builtin/gc.c msgid "frequency" msgstr "频率" @@ -9329,10 +9515,6 @@ msgid "Final output: %d %s\n" msgstr "最终输出:%d %s\n" #: builtin/log.c -msgid "unable to create temporary object directory" -msgstr "æ— æ³•åˆ›å»ºä¸´æ—¶å¯¹è±¡ç›®å½•" - -#: builtin/log.c #, c-format msgid "git show %s: bad file" msgstr "git show %s: æŸå的文件" @@ -9489,8 +9671,12 @@ msgid "max length of output filename" msgstr "输出文件å的最大长度" #: builtin/log.c -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "使用 [RFC PATCH] 代替 [PATCH]" +msgid "rfc" +msgstr "RFC" + +#: builtin/log.c +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "在 'PATCH' 之剿·»åŠ <RFC> (默认为 'RFC')" #: builtin/log.c msgid "cover-from-description-mode" @@ -9834,11 +10020,11 @@ msgstr "" #: builtin/ls-remote.c msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<坿‰§è¡Œæ–‡ä»¶>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<坿‰§è¡Œæ–‡ä»¶>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<é”®>]\n" " [--symref] [<仓库> [<模å¼>...]]" @@ -9859,9 +10045,13 @@ msgid "limit to tags" msgstr "ä»…é™äºŽæ ‡ç¾" #: builtin/ls-remote.c -msgid "limit to heads" +msgid "limit to branches" msgstr "ä»…é™äºŽåˆ†æ”¯" +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "已弃用的 --branches åŒä¹‰è¯" + #: builtin/ls-remote.c msgid "do not show peeled tags" msgstr "䏿˜¾ç¤ºå·²è§£æžçš„æ ‡ç¾" @@ -10052,18 +10242,6 @@ msgstr "使用基于 diff3 çš„åˆå¹¶" msgid "use a zealous diff3 based merge" msgstr "ä½¿ç”¨åŸºäºŽç‹‚çƒ diff3(zealous diff3)的åˆå¹¶" -#: builtin/merge-file.c -msgid "for conflicts, use our version" -msgstr "如果冲çªï¼Œä½¿ç”¨æˆ‘们的版本" - -#: builtin/merge-file.c -msgid "for conflicts, use their version" -msgstr "如果冲çªï¼Œä½¿ç”¨ä»–们的版本" - -#: builtin/merge-file.c -msgid "for conflicts, use a union version" -msgstr "如果冲çªï¼Œä½¿ç”¨è”åˆç‰ˆæœ¬" - #: builtin/merge-file.c diff.c msgid "<algorithm>" msgstr "<算法>" @@ -10359,7 +10537,7 @@ msgstr "ä¸èƒ½å†™å…¥ç´¢å¼•。" msgid "Not handling anything other than two heads merge." msgstr "未处ç†ä¸¤ä¸ªå¤´åˆå¹¶ä¹‹å¤–的任何æ“作。" -#: builtin/merge.c +#: builtin/merge.c builtin/sparse-checkout.c #, c-format msgid "unable to write %s" msgstr "ä¸èƒ½å†™ %s" @@ -10651,6 +10829,10 @@ msgid "write multi-pack bitmap" msgstr "写入多包ä½å›¾" #: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "å†™å…¥ä¸€ä¸ªæ–°çš„å¢žé‡ MIDX" + +#: builtin/multi-pack-index.c msgid "write multi-pack index containing only given indexes" msgstr "写入åªåŒ…括给定索引的多包索引" @@ -13048,6 +13230,39 @@ msgstr "未指定è¦åˆ 除的引用日志" 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]" + +#: builtin/refs.c +msgid "git refs verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +#: builtin/refs.c +msgid "specify the reference format to convert to" +msgstr "指定è¦è½¬æ¢çš„å¼•ç”¨æ ¼å¼" + +#: builtin/refs.c +msgid "perform a non-destructive dry-run" +msgstr "进行éžç ´å性的试è¿è¡Œï¼ˆdry-run)" + +#: builtin/refs.c +msgid "missing --ref-format=<format>" +msgstr "缺少 --ref-format=<æ ¼å¼>" + +#: builtin/refs.c +#, c-format +msgid "repository already uses '%s' format" +msgstr "仓库已使用 '%s' æ ¼å¼" + +#: builtin/refs.c +msgid "enable strict checking" +msgstr "å¯ç”¨ä¸¥æ ¼çš„æ£€æŸ¥" + +#: builtin/refs.c +msgid "'git refs verify' takes no arguments" +msgstr "'git refs verify' 䏿ޥå—任何傿•°" + #: builtin/remote.c msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" @@ -13392,10 +13607,6 @@ msgstr "* 远程 %s" msgid " Fetch URL: %s" msgstr " 获å–地å€ï¼š%s" -#: builtin/remote.c -msgid "(no URL)" -msgstr "(æ— URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -13406,6 +13617,10 @@ msgid " Push URL: %s" msgstr " 推é€åœ°å€ï¼š%s" #: builtin/remote.c +msgid "(no URL)" +msgstr "(æ— URL)" + +#: builtin/remote.c #, c-format msgid " HEAD branch: %s" msgstr " HEAD 分支:%s" @@ -13542,11 +13757,6 @@ msgid "return all URLs" msgstr "返回所有 URL 地å€" #: builtin/remote.c -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "没有给远程仓库 '%s' 设定 URL" - -#: builtin/remote.c msgid "manipulate push URLs" msgstr "æ“ä½œæŽ¨é€ URLS" @@ -14793,12 +15003,12 @@ msgstr "未知的哈希算法" #: builtin/show-ref.c msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<模å¼>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<模å¼>...]" #: builtin/show-ref.c msgid "" @@ -14827,12 +15037,12 @@ msgid "failed to look up reference" msgstr "æ— æ³•æ‰¾åˆ°å¼•ç”¨" #: builtin/show-ref.c -msgid "only show tags (can be combined with heads)" -msgstr "åªæ˜¾ç¤ºæ ‡ç¾ï¼ˆå¯ä»¥å’Œå¤´å…±ç”¨ï¼‰" +msgid "only show tags (can be combined with --branches)" +msgstr "ä»…æ˜¾ç¤ºæ ‡ç¾ï¼ˆå¯ä¸Ž --branches 组åˆä½¿ç”¨ï¼‰" #: builtin/show-ref.c -msgid "only show heads (can be combined with tags)" -msgstr "åªæ˜¾ç¤ºå¤´ï¼ˆå¯ä»¥å’Œæ ‡ç¾å…±ç”¨ï¼‰" +msgid "only show branches (can be combined with --tags)" +msgstr "仅显示分支(å¯ä¸Ž --tags 组åˆä½¿ç”¨ï¼‰" #: builtin/show-ref.c msgid "check for reference existence without resolving" @@ -14895,6 +15105,11 @@ msgid "failed to create directory for sparse-checkout file" msgstr "æ— æ³•ä¸ºç¨€ç–æ£€å‡ºæ–‡ä»¶åˆ›å»ºç›®å½•" #: builtin/sparse-checkout.c +#, c-format +msgid "unable to fdopen %s" +msgstr "ä¸èƒ½ fdopen %s" + +#: builtin/sparse-checkout.c msgid "failed to initialize worktree config" msgstr "æ— æ³•åˆå§‹åŒ–å·¥ä½œæ ‘é…ç½®" @@ -15443,8 +15658,8 @@ msgstr "ä¸èƒ½ä»Ž '%s' 创建哈希对象" #: builtin/submodule--helper.c #, c-format -msgid "unexpected mode %o\n" -msgstr "æ„å¤–çš„æ¨¡å¼ %o\n" +msgid "unexpected mode %o" +msgstr "æ„å¤–çš„æ¨¡å¼ %o" #: builtin/submodule--helper.c msgid "use the commit stored in the index instead of the submodule HEAD" @@ -15579,20 +15794,20 @@ msgstr "ä¸èƒ½è¯†åˆ« submodule.alternateErrorStrategy çš„å–值 '%s'" msgid "Value '%s' for submodule.alternateLocation is not recognized" msgstr "ä¸èƒ½è¯†åˆ« submodule.alternateLocation çš„å–值 '%s'" -#: builtin/submodule--helper.c +#: builtin/submodule--helper.c submodule.c #, c-format msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "æ‹’ç»åœ¨å¦ä¸€ä¸ªå模组的 git 目录ä¸åˆ›å»º/使用 '%s'" #: builtin/submodule--helper.c #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "æ— æ³•å…‹éš† '%s' åˆ°åæ¨¡ç»„路径 '%s'" +msgid "directory not empty: '%s'" +msgstr "目录éžç©ºï¼š'%s'" #: builtin/submodule--helper.c #, c-format -msgid "directory not empty: '%s'" -msgstr "目录éžç©ºï¼š'%s'" +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "æ— æ³•å…‹éš† '%s' åˆ°åæ¨¡ç»„路径 '%s'" #: builtin/submodule--helper.c #, c-format @@ -16033,9 +16248,11 @@ msgstr "æ›´æ–°çš„åŽŸå› " #: builtin/tag.c msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" -"git tag [-a | -s | -u <ç§é’¥ ID>] [-f] [-m <消æ¯> | -F <文件>] [-e]\n" +"git tag [-a | -s | -u <ç§é’¥ id>] [-f] [-m <消æ¯> | -F <文件>] [-e]\n" +" [(--trailer <令牌>[(=|:)<值>])...]\n" " <æ ‡ç¾å> [<æäº¤> | <对象>]" #: builtin/tag.c @@ -17080,10 +17297,6 @@ msgid "Repository lacks these prerequisite commits:" msgstr "仓库ä¸ç¼ºå°‘这些必备的æäº¤ï¼š" #: bundle.c -msgid "need a repository to verify a bundle" -msgstr "需è¦ä¸€ä¸ªä»“åº“æ¥æ ¡éªŒä¸€ä¸ªå½’档包" - -#: bundle.c msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -17604,6 +17817,10 @@ msgid "Manage reflog information" msgstr "ç®¡ç† reflog ä¿¡æ¯" #: command-list.h +msgid "Low-level access to refs" +msgstr "对引用的低级访问" + +#: command-list.h msgid "Manage set of tracked repositories" msgstr "管ç†å·²è·Ÿè¸ªä»“库" @@ -18000,6 +18217,13 @@ msgid "commit-graph required commit data chunk missing or corrupted" msgstr "æäº¤å›¾æ‰€éœ€çš„æäº¤æ•°æ®å—缺失或æŸå" #: commit-graph.c +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "由于ä¸å…¼å®¹çš„设置,æ£åœ¨ç¦ç”¨æäº¤å›¾å±‚ '%s' 的布隆过滤器" + +#: commit-graph.c msgid "commit-graph has no base graphs chunk" msgstr "æäº¤å›¾æ²¡æœ‰åŸºç¡€å›¾å½¢å—" @@ -18111,7 +18335,7 @@ msgstr "æ— æ³•å†™å…¥æ£ç¡®æ•°é‡çš„基础图形 ID" msgid "unable to create temporary graph layer" msgstr "æ— æ³•åˆ›å»ºä¸´æ—¶å›¾å±‚" -#: commit-graph.c +#: commit-graph.c midx-write.c #, c-format msgid "unable to adjust shared permissions for '%s'" msgstr "æ— æ³•ä¸º '%s' 调整共享æƒé™" @@ -18159,6 +18383,13 @@ msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" msgstr "æ£å°è¯•写æäº¤å›¾ï¼Œä½†æ˜¯ 'core.commitGraph' 被ç¦ç”¨" #: commit-graph.c +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "å°è¯•写入æäº¤å›¾ï¼Œä½†ä¸æ”¯æŒ 'commitGraph.changedPathsVersion' (%d)" + +#: commit-graph.c msgid "too many commits to write graph" msgstr "æäº¤å¤ªå¤šä¸èƒ½ç”»å›¾" @@ -19453,7 +19684,7 @@ msgstr "color-moved-ws:allow-indentation-change ä¸èƒ½ä¸Žå…¶å®ƒç©ºç™½å—符模 msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "é…ç½®å˜é‡ 'diff.submodule' 未知的å–值:'%s'" -#: diff.c transport.c +#: diff.c merge-recursive.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "é…ç½® '%s' 未知的å–值:%s" @@ -20418,16 +20649,19 @@ msgstr "å› ä¸ºç¼ºå°‘ Unix å¥—æŽ¥å—æ”¯æŒï¼Œå¥—接å—目录 '%s' 与 fsmonitor ä msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <路径>] [-c <åç§°>=<å–值>]\n" " [--exec-path[=<路径>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<路径>] [--work-tree=<路径>] [--namespace=<åç§°>]\n" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [\"--" +"no-lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<路径>]\n" +" [--work-tree=<路径>] [--namespace=<åç§°>]\n" " [--config-env=<åç§°>=<环境å˜é‡>] <命令> [<傿•°>]" #: git.c @@ -20834,14 +21068,14 @@ msgstr "" "é…ç½® `git config advice.ignoredHook false` æ¥å…³é—è¿™æ¡è¦å‘Šã€‚" #: http-fetch.c +msgid "not a git repository" +msgstr "䏿˜¯ git 仓库" + +#: http-fetch.c #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "--packfile çš„å‚æ•°å¿…须是有效的哈希值(得到 '%s')" -#: http-fetch.c -msgid "not a git repository" -msgstr "䏿˜¯ git 仓库" - #: http.c #, c-format msgid "negative value for http.postBuffer; defaulting to %d" @@ -20856,6 +21090,10 @@ msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "䏿”¯æŒå…¬é’¥æ–‡ä»¶é”å®šï¼Œå› ä¸º cURL < 7.39.0" #: http.c +msgid "Unknown value for http.proactiveauth" +msgstr "http.proactiveauth 为未知å–值" + +#: http.c msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "䏿”¯æŒ CURLSSLOPT_NO_REVOKEï¼Œå› ä¸º cURL < 7.44.0" @@ -20875,6 +21113,14 @@ msgid "Could not set SSL backend to '%s': already set" msgstr "æ— æ³•å°† SSL åŽç«¯è®¾ç½®ä¸º '%s':已ç»è®¾ç½®" #: http.c +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "æ‹’ç»ä»Ž http.cookiefile '-' è¯»å– cookies" + +#: http.c +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "å› ä¸º http.cookiefile 为空,忽略 http.savecookies" + +#: http.c #, c-format msgid "" "unable to update url base from redirection:\n" @@ -20917,6 +21163,7 @@ msgstr "" "\n" "æ¥è®¾ç½®æ‚¨è´¦å·çš„缺çœèº«ä»½æ ‡è¯†ã€‚\n" "å¦‚æžœä»…åœ¨æœ¬ä»“åº“è®¾ç½®èº«ä»½æ ‡è¯†ï¼Œåˆ™çœç•¥ --global 傿•°ã€‚\n" +"\n" #: ident.c msgid "no email was given and auto-detection is disabled" @@ -21037,6 +21284,10 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "ä¸èƒ½åˆ›å»º '%s.lock':%s" +#: log-tree.c +msgid "unable to create temporary object directory" +msgstr "æ— æ³•åˆ›å»ºä¸´æ—¶å¯¹è±¡ç›®å½•" + #: loose.c #, c-format msgid "could not write loose object index %s" @@ -21044,8 +21295,8 @@ msgstr "ä¸èƒ½å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s" #: loose.c #, c-format -msgid "failed to write loose object index %s\n" -msgstr "æ— æ³•å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s\n" +msgid "failed to write loose object index %s" +msgstr "æ— æ³•å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s" #: ls-refs.c #, c-format @@ -21080,10 +21331,10 @@ msgstr "æ— æ³•åˆå¹¶å模组 %s (没有åˆå¹¶åŸºçº¿ï¼‰" msgid "Failed to merge submodule %s (commits not present)" msgstr "æ— æ³•åˆå¹¶å模组 %s(æäº¤ä¸å˜åœ¨ï¼‰" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "æ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "é”™è¯¯ï¼šæ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" #: merge-ort.c merge-recursive.c #, c-format @@ -21115,14 +21366,15 @@ msgstr "" "æ— æ³•åˆå¹¶å模组 %s,但是å˜åœ¨å¤šä¸ªå¯èƒ½çš„åˆå¹¶ï¼š\n" "%s" -#: merge-ort.c merge-recursive.c -msgid "failed to execute internal merge" -msgstr "æ— æ³•æ‰§è¡Œå†…éƒ¨åˆå¹¶" +#: merge-ort.c +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "é”™è¯¯ï¼šæ— æ³•ä¸º %s 执行内部åˆå¹¶" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "unable to add %s to database" -msgstr "ä¸èƒ½æ·»åŠ %s 至对象库" +msgid "error: unable to add %s to database" +msgstr "错误:ä¸èƒ½æ·»åŠ %s 至对象库" #: merge-ort.c merge-recursive.c #, c-format @@ -21220,15 +21472,15 @@ msgstr "" msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s." msgstr "冲çªï¼ˆé‡å‘½å/åˆ é™¤ï¼‰ï¼š%1$s 在 %3$s ä¸é‡å‘½å为 %2$s,但在 %4$s ä¸åˆ 除。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "cannot read object %s" -msgstr "ä¸èƒ½è¯»å–对象 %s" +msgid "error: cannot read object %s" +msgstr "错误:ä¸èƒ½è¯»å–对象 %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "object %s is not a blob" -msgstr "对象 %s 䏿˜¯ä¸€ä¸ªæ•°æ®å¯¹è±¡" +msgid "error: object %s is not a blob" +msgstr "错误:对象 %s 䏿˜¯ä¸€ä¸ªæ•°æ®å¯¹è±¡" #: merge-ort.c #, c-format @@ -21384,6 +21636,11 @@ msgstr "ä¸çŸ¥é“å¦‚ä½•å¤„ç† %06o %s '%s'" #: merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "æ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" + +#: merge-recursive.c +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "忍¡ç»„ %s 快进到如下æäº¤ï¼š" @@ -21428,6 +21685,15 @@ msgid "Failed to merge submodule %s (multiple merges found)" msgstr "æ— æ³•åˆå¹¶å模组 %s (å‘现多个åˆå¹¶ï¼‰" #: merge-recursive.c +msgid "failed to execute internal merge" +msgstr "æ— æ³•æ‰§è¡Œå†…éƒ¨åˆå¹¶" + +#: merge-recursive.c +#, c-format +msgid "unable to add %s to database" +msgstr "ä¸èƒ½æ·»åŠ %s 至对象库" + +#: merge-recursive.c #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "错误:拒ç»ä¸¢å¤±æœªè·Ÿè¸ªæ–‡ä»¶ '%s',而是写入 %s。" @@ -21541,6 +21807,16 @@ msgstr "" "%4$s->%5$s" #: merge-recursive.c +#, c-format +msgid "cannot read object %s" +msgstr "ä¸èƒ½è¯»å–对象 %s" + +#: merge-recursive.c +#, c-format +msgid "object %s is not a blob" +msgstr "对象 %s 䏿˜¯ä¸€ä¸ªæ•°æ®å¯¹è±¡" + +#: merge-recursive.c msgid "modify" msgstr "修改" @@ -21645,10 +21921,6 @@ msgid "malformed line: %s" msgstr "æ ¼å¼é”™è¯¯çš„行:%s" #: midx-write.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "忽略已å˜åœ¨çš„å¤šåŒ…ç´¢å¼•ï¼Œæ ¡éªŒç ä¸åŒ¹é…" - -#: midx-write.c msgid "could not load pack" msgstr "ä¸èƒ½è½½å…¥åŒ…" @@ -21658,6 +21930,24 @@ msgid "could not open index for %s" msgstr "ä¸èƒ½æ‰“å¼€ %s 的索引" #: midx-write.c +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "æ— æ³•å°† '%s' 链接至 '%s'" + +#: midx-write.c midx.c +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "æ— æ³•æ¸…ç†ä½äºŽ %s 的多包索引" + +#: midx-write.c +msgid "cannot write incremental MIDX with bitmap" +msgstr "æ— æ³•ä½¿ç”¨ä½å›¾å†™å…¥å¢žé‡ MIDX" + +#: midx-write.c +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "忽略已å˜åœ¨çš„å¤šåŒ…ç´¢å¼•ï¼Œæ ¡éªŒç ä¸åŒ¹é…" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "æ·»åŠ åŒ…æ–‡ä»¶åˆ°å¤šåŒ…ç´¢å¼•" @@ -21690,14 +21980,30 @@ msgid "refusing to write multi-pack .bitmap without any objects" msgstr "æ‹’ç»å†™å…¥æ²¡æœ‰ä»»ä½•对象的多包ä½å›¾" #: midx-write.c +msgid "unable to create temporary MIDX layer" +msgstr "æ— æ³•åˆ›å»ºä¸´æ—¶ MIDX 层" + +#: midx-write.c msgid "could not write multi-pack bitmap" msgstr "æ— æ³•å†™å…¥å¤šåŒ…ä½å›¾" #: midx-write.c +msgid "unable to open multi-pack-index chain file" +msgstr "æ— æ³•æ‰“å¼€å¤šåŒ…ç´¢å¼•é“¾æ–‡ä»¶" + +#: midx-write.c +msgid "unable to rename new multi-pack-index layer" +msgstr "æ— æ³•é‡å‘½å新的多包索引层" + +#: midx-write.c msgid "could not write multi-pack-index" msgstr "æ— æ³•å†™å…¥å¤šåŒ…ç´¢å¼•" #: midx-write.c +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "增é‡å¤šåŒ…索引ä¸çš„包ä¸èƒ½è¿‡æœŸ" + +#: midx-write.c msgid "Counting referenced objects" msgstr "æ£åœ¨å¯¹å¼•用对象计数" @@ -21706,6 +22012,10 @@ msgid "Finding and deleting unreferenced packfiles" msgstr "æ£åœ¨æŸ¥æ‰¾å’Œåˆ 除未引用的包文件" #: midx-write.c +msgid "cannot repack an incremental multi-pack-index" +msgstr "æ— æ³•é‡æ–°æ‰“包增é‡å¤šåŒ…索引" + +#: midx-write.c msgid "could not start pack-objects" msgstr "ä¸èƒ½å¼€å§‹ pack-objects" @@ -21777,6 +22087,33 @@ msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "å¤šåŒ…ç´¢å¼•åŒ…åæ— åºï¼š'%s' 在 '%s' 之å‰" #: midx.c +msgid "multi-pack-index chain file too small" +msgstr "多包索引链文件太å°" + +#: midx.c +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "基线的 MIDX ä¸åŒ…的数é‡è¿‡é«˜ï¼š%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "基线的 MIDX ä¸å¯¹è±¡çš„æ•°é‡è¿‡é«˜ï¼š%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "æ— æ•ˆçš„å¤šåŒ…ç´¢å¼•é“¾ï¼šç¬¬ '%s' è¡Œä¸æ˜¯å“ˆå¸Œå€¼" + +#: midx.c +msgid "unable to find all multi-pack index files" +msgstr "æ— æ³•æ‰¾åˆ°æ‰€æœ‰çš„å¤šåŒ…ç´¢å¼•æ–‡ä»¶" + +#: midx.c +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "æ— æ•ˆçš„ MIDX 对象ä½ç½®ï¼ŒMIDX å¯èƒ½å·²æŸå" + +#: midx.c #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "错的 pack-int-id:%u(共有 %u 个包)" @@ -21799,11 +22136,6 @@ msgid "multi-pack-index large offset out of bounds" msgstr "多包索引大å移区越界" #: midx.c -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "æ— æ³•æ¸…ç†ä½äºŽ %s 的多包索引" - -#: midx.c msgid "multi-pack-index file exists, but failed to parse" msgstr "多包索引文件å˜åœ¨ï¼Œä½†æ— 法解æž" @@ -22062,6 +22394,16 @@ msgstr "缺少 %s 到 %s çš„æ˜ å°„" #: object-file.c #, c-format +msgid "unable to open %s" +msgstr "ä¸èƒ½æ‰“å¼€ %s" + +#: object-file.c +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "文件 '%s' å’Œ '%s' 的内容ä¸åŒ" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "æ— æ³•å†™æ–‡ä»¶ %s" @@ -22168,11 +22510,6 @@ msgstr "%s 䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ '%s' 对象" #: object-file.c #, c-format -msgid "unable to open %s" -msgstr "ä¸èƒ½æ‰“å¼€ %s" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s 的哈希值ä¸åŒ¹é…(预期 %s)" @@ -22394,6 +22731,20 @@ msgid "hash mismatch %s" msgstr "哈希值与 %s ä¸åŒ¹é…" #: pack-bitmap-write.c +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "写入ä½å›¾ç´¢å¼•æ—¶å˜åœ¨é‡å¤æ¡ç›®ï¼š'%s'" + +#: pack-bitmap-write.c +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "å°è¯•å˜å‚¨æœªé€‰å®šçš„æäº¤ï¼š'%s'" + +#: pack-bitmap-write.c +msgid "too many pseudo-merges" +msgstr "太多伪åˆå¹¶" + +#: pack-bitmap-write.c msgid "trying to write commit not in index" msgstr "å°è¯•写入未在索引ä¸çš„æäº¤" @@ -22423,6 +22774,19 @@ msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "æŸåçš„ä½å›¾ç´¢å¼•(太å°ï¼Œå®¹ä¸ä¸‹æŸ¥è¯¢è¡¨ï¼‰" #: pack-bitmap.c +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "æŸåçš„ä½å›¾ç´¢å¼•文件(太çŸè€Œæ— 法容纳伪åˆå¹¶è¡¨å¤´ï¼‰" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "æŸåçš„ä½å›¾ç´¢å¼•(太çŸè€Œæ— 法容纳伪åˆå¹¶è¡¨ï¼‰" + +#: pack-bitmap.c +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "æŸåçš„ä½å›¾ç´¢å¼•,伪åˆå¹¶è¡¨è¿‡çŸ" + +#: pack-bitmap.c #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "ä½å›¾ç´¢å¼•ä¸çš„é‡å¤æ¡ç›®ï¼š'%s'" @@ -22537,6 +22901,11 @@ msgstr "ä½å›¾ç»“æžœä¸ä¸€è‡´" #: pack-bitmap.c #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "伪åˆå¹¶ç´¢å¼•超出范围 (%<PRIu32> >= %<PRIuMAX>)" + +#: pack-bitmap.c +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "æ— æ³•åœ¨åŒ… '%2$s' åç§» %3$<PRIuMAX> 䏿‰¾åˆ° '%1$s'" @@ -22988,6 +23357,10 @@ msgid "unable to parse --pretty format" msgstr "ä¸èƒ½è§£æž --pretty æ ¼å¼" #: promisor-remote.c +msgid "lazy fetching disabled; some objects may not be available" +msgstr "ç¦ç”¨å»¶è¿ŸèŽ·å–,æŸäº›å¯¹è±¡å¯èƒ½ä¸å¯ç”¨" + +#: promisor-remote.c msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remoteï¼šæ— æ³•æ´¾ç”Ÿ fetch å进程" @@ -23017,6 +23390,72 @@ msgstr "object-infoï¼šåœ¨å‚æ•°ä¹‹åŽåº”有一个 flush" msgid "Removing duplicate objects" msgstr "æ£åœ¨åˆ 除é‡å¤å¯¹è±¡" +#: pseudo-merge.c +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "æœªèƒ½åŠ è½½ %s 的伪åˆå¹¶æ£åˆ™è¡¨è¾¾å¼ï¼š'%s'" + +#: pseudo-merge.c +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s 必须为éžè´Ÿæ•´æ•°ï¼Œä½¿ç”¨é»˜è®¤å€¼" + +#: pseudo-merge.c +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s 必须介于 0 到 1 之间,使用默认值" + +#: pseudo-merge.c +#, c-format +msgid "%s must be positive, using default" +msgstr "%s å¿…é¡»ä¸ºæ£æ•°ï¼Œä½¿ç”¨é»˜è®¤å€¼" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "伪åˆå¹¶ç»„ '%s' 缺少所需的模å¼" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "伪åˆå¹¶ç»„ '%s' åœ¨ç¨³å®šé˜ˆå€¼ä¹‹å‰æœ‰ä¸ç¨³å®šé˜ˆå€¼" + +#: pseudo-merge.c +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "æ¥è‡ª config 的伪åˆå¹¶æ£åˆ™è¡¨è¾¾å¼æœ‰å¤ªå¤šçš„æ•èŽ·ç»„ï¼ˆæœ€å¤š %<PRIuMAX> 个)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "扩展伪åˆå¹¶è¯»å–越界 (%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "扩展伪åˆå¹¶æ¡ç›®å¤ªçŸï¼ˆ%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "æ— æ³•åœ¨æäº¤ %1$s çš„åç§» %2$<PRIuMAX> 䏿‰¾åˆ°ä¼ªåˆå¹¶" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "扩展伪åˆå¹¶æŸ¥æ‰¾è¶Šç•Œ (%<PRIu32> >= %<PRIu32>)" + +#: pseudo-merge.c +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "越界读å–:(%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "æ— æ³•è¯»å–æäº¤ %s 的扩展伪åˆå¹¶è¡¨" + #: range-diff.c msgid "could not start `log`" msgstr "ä¸èƒ½å¯åЍ `log`" @@ -23517,6 +23956,11 @@ msgstr "æœŸæœ›çš„æ ¼å¼ï¼š%%(ahead-behind:<æäº¤å·>)" #: ref-filter.c #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "æœŸæœ›çš„æ ¼å¼ï¼š%%(is-base:<æäº¤å·>)" + +#: ref-filter.c +#, c-format msgid "malformed field name: %.*s" msgstr "æ ¼å¼é”™è¯¯çš„å—æ®µå:%.*s" @@ -23726,12 +24170,21 @@ msgid "log for %s is empty" msgstr "%s 的日志为空" #: refs.c +msgid "refusing to force and skip creation of reflog" +msgstr "æ‹’ç»æ—¢å¼ºåˆ¶åˆè·³è¿‡åˆ›å»ºå¼•用日志" + +#: refs.c #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "æ‹’ç»æ›´æ–°æœ‰é”™è¯¯åç§° '%s' 的引用" #: refs.c #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "æ‹’ç»æ›´æ–°ä¼ªå¼•用 '%s'" + +#: refs.c +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "对引用 '%s' 执行 update_ref 失败:%s" @@ -23768,6 +24221,36 @@ msgstr "æ— æ³•åˆ é™¤å¼•ç”¨ %s:%s" msgid "could not delete references: %s" msgstr "æ— æ³•åˆ é™¤å¼•ç”¨ï¼š%s" +#: refs.c +#, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "å·²å®Œæˆ refs 的试è¿è¡Œè¿ç§»ï¼Œç»“æžœå¯åœ¨ '%s' 处找到\n" + +#: refs.c +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "æ— æ³•åˆ é™¤ä¸´æ—¶è¿ç§»ç›®å½• '%s'" + +#: refs.c +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "è¿ç§»çš„引用å¯ä»¥åœ¨ '%s' 处找到" + +#: refs/files-backend.c refs/reftable-backend.c +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "æ— æ³•é”定引用 '%s'ï¼šé¢„æœŸç›®æ ‡ä¸º '%s' 的符å·å¼•用:但是是普通引用" + +#: refs/files-backend.c +#, c-format +msgid "cannot open directory %s" +msgstr "æ— æ³•æ‰“å¼€ç›®å½• %s" + +#: refs/files-backend.c +msgid "Checking references consistency" +msgstr "æ£åœ¨æ£€æŸ¥å¼•用一致性" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -24538,12 +25021,16 @@ msgid "create repository within 'src' directory" msgstr "在 'src' 目录ä¸åˆ›å»ºä»“库" #: scalar.c +msgid "specify if tags should be fetched during clone" +msgstr "å¦‚è‹¥åº”åœ¨å…‹éš†æœŸé—´èŽ·å–æ ‡ç¾åˆ™æŒ‡å®š" + +#: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<登记>]" +"\t[--[no-]src] [--[no-]tags] <url> [<登记>]" #: scalar.c #, c-format @@ -24567,6 +25054,11 @@ msgstr "æ— æ³•åœ¨ '%s' ä¸é…置远程" #: scalar.c #, c-format +msgid "could not disable tags in '%s'" +msgstr "æ— æ³•ç¦ç”¨ '%s' ä¸çš„æ ‡ç¾" + +#: scalar.c +#, c-format msgid "could not configure '%s'" msgstr "æ— æ³•é…ç½® '%s'" @@ -25159,6 +25651,53 @@ msgstr "update-ref 需è¦ä¸€ä¸ªå®Œæ•´çš„引用å,例如:refs/heads/%s" #: sequencer.c #, c-format +msgid "'%s' does not accept merge commits" +msgstr "'%s' 䏿ޥå—åˆå¹¶æäº¤" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"'pick' 䏿ޥå—åˆå¹¶æäº¤ã€‚如果您想è¦é‡æ”¾åˆå¹¶ï¼Œ\n" +"请在æäº¤ä¸Šä½¿ç”¨ 'merge -C'。" + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"'reword' 䏿ޥå—åˆå¹¶æäº¤ã€‚å¦‚æžœæ‚¨æƒ³é‡æ”¾åˆå¹¶å¹¶é‡å†™æäº¤æ¶ˆæ¯ï¼Œ\n" +"请在æäº¤ä¸Šä½¿ç”¨ 'merge -c'" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +#: sequencer.c +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"'editâ€' 䏿ޥå—åˆå¹¶æäº¤ã€‚如果您想è¦é‡æ”¾åˆå¹¶ï¼Œ\n" +"请在æäº¤ä¸Šä½¿ç”¨ 'merge -C',然åŽä½¿ç”¨ 'break'\n" +"将控制æƒäº¤è¿˜ç»™æ‚¨ï¼Œä»¥ä¾¿æ‚¨å¯ä»¥æ‰§è¡Œ\n" +"'git commit --amend && git rebase --continue'。" + +#: sequencer.c +msgid "cannot squash merge commit into another commit" +msgstr "æ— æ³•å°†åˆå¹¶æäº¤åŽ‹ç¼©åˆ°å¦ä¸€ä¸ªæäº¤ä¸" + +#: sequencer.c +#, c-format msgid "invalid command '%.*s'" msgstr "æ— æ•ˆå‘½ä»¤ '%.*s'" @@ -25307,9 +25846,8 @@ msgid "cannot read HEAD" msgstr "ä¸èƒ½è¯»å– HEAD" #: sequencer.c -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "æ— æ³•æ‹·è´ '%s' 至 '%s'" +msgid "could not write commit message file" +msgstr "æ— æ³•å†™å…¥æäº¤è¯´æ˜Žæ–‡ä»¶" #: sequencer.c #, c-format @@ -25788,6 +26326,24 @@ msgid "failed to stat '%*s%s%s'" msgstr "æ— æ³•èŽ·å– '%*s%s%s' 状æ€ï¼ˆstat)" #: setup.c +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory '%s' 䏿˜¯ç»å¯¹è·¯å¾„" + +#: setup.c +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"在 '%s' 检测到å¯ç–‘的仓库所有æƒ\n" +"%sè¦ä¸ºæœ¬ä»“库创建特例,请è¿è¡Œï¼š\n" +"\n" +"\tgit config --global --add safe.directory %s" + +#: setup.c msgid "Unable to read current working directory" msgstr "ä¸èƒ½è¯»å–当å‰å·¥ä½œç›®å½•" @@ -25812,19 +26368,6 @@ msgstr "" #: setup.c #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"在 '%s' 检测到å¯ç–‘的仓库所有æƒ\n" -"%sè¦ä¸ºæœ¬ä»“库创建特例,请è¿è¡Œï¼š\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#: setup.c -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" msgstr "æ— æ³•ä½¿ç”¨çº¯ä»“åº“ '%s' (safe.bareRepository 为 '%s')" @@ -26189,6 +26732,16 @@ msgstr "忍¡ç»„ git 目录 '%s' ä½äºŽ git 目录 '%.*s' ä¸" #: submodule.c #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "æœŸæœ›åæ¨¡ç»„的父目录 '%.*s' 䏿˜¯ä¸€ä¸ªç¬¦å·é“¾æŽ¥ï¼Œå模组路径为 '%s'" + +#: submodule.c +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "é¢„æœŸåæ¨¡ç»„路径 '%s' 䏿˜¯ç¬¦å·é“¾æŽ¥" + +#: submodule.c +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "䏿”¯æŒå¯¹æœ‰å¤šä¸ªå·¥ä½œåŒºçš„忍¡ç»„ '%s' 执行 relocate_gitdir" @@ -26233,11 +26786,6 @@ msgid "no remote configured to get bundle URIs from" msgstr "没有远程被设置为å¯ä»¥èŽ·å–归档包 URI" #: t/helper/test-bundle-uri.c -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "远程 '%s' 没有设置 URL" - -#: t/helper/test-bundle-uri.c msgid "could not get the bundle-uri list" msgstr "æ— æ³•èŽ·å– bundle-uri 列表" @@ -26342,6 +26890,30 @@ msgstr "令牌" msgid "command token to send to the server" msgstr "å‘é€åˆ°æœåŠ¡å™¨çš„å‘½ä»¤ä»¤ç‰Œ" +#: t/unit-tests/unit-test.c +msgid "unit-test [<options>]" +msgstr "unit-test [<选项>]" + +#: t/unit-tests/unit-test.c +msgid "immediately exit upon the first failed test" +msgstr "第一次测试失败åŽç«‹å³é€€å‡º" + +#: t/unit-tests/unit-test.c +msgid "suite[::test]" +msgstr "suite[::测试用例]" + +#: t/unit-tests/unit-test.c +msgid "run only test suite or individual test <suite[::test]>" +msgstr "åªè¿è¡Œæµ‹è¯•套件或å•独的测试 <测试套件[::测试用例]>" + +#: t/unit-tests/unit-test.c +msgid "suite" +msgstr "测试套件" + +#: t/unit-tests/unit-test.c +msgid "exclude test suite <suite>" +msgstr "排除测试套件 <测试套件>" + #: trailer.c #, c-format msgid "running trailer command '%s' failed" @@ -27793,6 +28365,10 @@ msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases 和其它选项ä¸å…¼å®¹\n" #: git-send-email.perl +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases å’Œ --translate-aliases 是互斥的\n" + +#: git-send-email.perl msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -28025,29 +28601,29 @@ msgstr "æ— æ³•å‘é€ %s\n" #: git-send-email.perl #, perl-format -msgid "Dry-Sent %s\n" -msgstr "æ¼”ä¹ å‘é€ %s\n" +msgid "Dry-Sent %s" +msgstr "æ¼”ä¹ å‘é€ %s" #: git-send-email.perl #, perl-format -msgid "Sent %s\n" -msgstr "æ£å‘é€ %s\n" +msgid "Sent %s" +msgstr "å·²å‘é€ %s" #: git-send-email.perl -msgid "Dry-OK. Log says:\n" -msgstr "æ¼”ä¹ æˆåŠŸã€‚æ—¥å¿—è¯´ï¼š\n" +msgid "Dry-OK. Log says:" +msgstr "æ¼”ä¹ æˆåŠŸã€‚æ—¥å¿—è¯´ï¼š" #: git-send-email.perl -msgid "OK. Log says:\n" -msgstr "OK。日志说:\n" +msgid "OK. Log says:" +msgstr "æˆåŠŸã€‚æ—¥å¿—è¯´ï¼š" #: git-send-email.perl msgid "Result: " msgstr "结果:" #: git-send-email.perl -msgid "Result: OK\n" -msgstr "结果:OK\n" +msgid "Result: OK" +msgstr "结果:æˆåŠŸ" #: git-send-email.perl #, perl-format diff --git a/po/zh_TW.po b/po/zh_TW.po index f554381a7a..5e6818f453 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -21,14 +21,17 @@ # # Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023, 2024. # Kaiyang Wu <self@origincode.me>, 2022. -# lumynou5 <lumynou5.tw@gmail.com>, 2023, 2024. +# Lumynous <lumynou5.tw@gmail.com>, 2023, 2024. # Kisaragi Hiu <mail@kisaragi-hiu.com>, 2024. +# Ngoo Ka-iu <willy04wu69@gmail.com>, 2024. +# Nightfeather Chen <slat@nightfeather.me>, 2024. +# hms5232 <hms5232@hhming.moe>, 2024. msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-04-28 18:52+0800\n" -"PO-Revision-Date: 2024-04-28 18:44+0800\n" +"POT-Creation-Date: 2024-10-05 01:20+0000\n" +"PO-Revision-Date: 2024-10-05 15:45+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" @@ -37,7 +40,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 3.4.2\n" +"X-Generator: Poedit 3.5\n" "X-ZhConverter: ç¹åŒ–姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | https://" "zhconvert.org\n" @@ -69,7 +72,7 @@ msgstr "æ›´æ–°" #: add-interactive.c #, c-format msgid "could not stage '%s'" -msgstr "ç„¡æ³•æš«å˜ â€œ%sâ€" +msgstr "無法暫å˜ã€Œ%sã€" #: add-interactive.c builtin/stash.c reset.c sequencer.c msgid "could not write index" @@ -89,7 +92,7 @@ msgstr "註:ç¾å·²ä¸å†è¿½è¹¤ %s。\n" #: add-interactive.c apply.c builtin/checkout.c builtin/reset.c #, c-format msgid "make_cache_entry failed for path '%s'" -msgstr "å° â€œ%s†路徑執行 make_cache_entry 失敗" +msgstr "å°ã€Œ%sã€è·¯å¾‘執行 make_cache_entry 失敗" #: add-interactive.c msgid "Revert" @@ -125,12 +128,12 @@ msgstr[0] "å·²åŠ å…¥ %d 個路徑\n" msgid "ignoring unmerged: %s" msgstr "忽略未åˆä½µé …目:%s" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "Only binary files changed.\n" msgstr "åªæœ‰äºŒé€²ä½æª”案更動了。\n" -#: add-interactive.c add-patch.c +#: add-interactive.c #, c-format msgid "No changes.\n" msgstr "沒有更動。\n" @@ -543,7 +546,7 @@ msgstr "" #: add-patch.c #, c-format msgid "could not parse hunk header '%.*s'" -msgstr "無法解æžå€å¡Šæ¨™é “%.*sâ€" +msgstr "無法解æžå€å¡Šæ¨™é 「%.*sã€" #: add-patch.c msgid "could not parse diff" @@ -556,7 +559,7 @@ msgstr "無法解æžä¸Šè‰²éŽçš„差異" #: add-patch.c #, c-format msgid "failed to run '%s'" -msgstr "無法執行 “%sâ€" +msgstr "無法執行「%sã€" #: add-patch.c msgid "mismatched output from interactive.diffFilter" @@ -625,7 +628,7 @@ msgstr "無法解æžå€å¡Šæ¨™é " #: add-patch.c msgid "'git apply --cached' failed" -msgstr "“git apply --cached†失敗" +msgstr "「git apply --cachedã€å¤±æ•—" #. TRANSLATORS: do not translate [y/n] #. The program will only accept that input at this point. @@ -636,7 +639,7 @@ msgstr "“git apply --cached†失敗" #: add-patch.c msgid "" "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " -msgstr "未套用您編輯的å€å¡Šã€‚是å¦é‡æ–°ç·¨è¼¯ï¼ˆè¼¸å…¥ “noâ€ æ¨æ£„ï¼ï¼‰ [y/n]? " +msgstr "未套用您編輯的å€å¡Šã€‚是å¦é‡æ–°ç·¨è¼¯ï¼ˆè¼¸å…¥ã€Œnoã€æ¨æ£„ï¼ï¼‰ [y/n]? " #: add-patch.c msgid "The selected hunks do not apply to the index!" @@ -660,7 +663,7 @@ msgid "" "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" -"p - print the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" "? - print help\n" msgstr "" "j - ç¶æŒæ¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–下一個未決定å€å¡Š\n" @@ -671,10 +674,15 @@ msgstr "" "/ - å°‹æ‰¾ç¬¦åˆæä¾›ä¹‹å¸¸è¦è¡¨ç¤ºå¼çš„å€å¡Š\n" "s - 分割目å‰å€å¡Šç‚ºæ›´å°çš„å€å¡Š\n" "e - 手動編輯目å‰å€å¡Š\n" -"p - 輸出目å‰å€å¡Š\n" +"p - 輸出目å‰å€å¡Šï¼Œã€ŒPã€åˆ†é 顯示\n" "? - 顯示說明\n" #: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "é æœŸæ”¶åˆ°ä¸€å€‹å—æ¯ï¼Œå»æ”¶åˆ°ã€Œ%sã€" + +#: add-patch.c msgid "No previous hunk" msgstr "沒有上一個å€å¡Š" @@ -697,7 +705,7 @@ msgstr "跳轉到哪個å€å¡Š? " #: add-patch.c #, c-format msgid "Invalid number: '%s'" -msgstr "無效數å—:“%sâ€" +msgstr "無效數å—:「%sã€" #: add-patch.c #, c-format @@ -736,8 +744,21 @@ msgid "Sorry, cannot edit this hunk" msgstr "å°ä¸èµ·ï¼Œç„¡æ³•編輯這個å€å¡Š" #: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "未知命令「%sã€ï¼ˆä½¿ç”¨ã€Œ?ã€ç²å–幫助)" + +#: add-patch.c msgid "'git apply' failed" -msgstr "“git apply†失敗" +msgstr "「git applyã€å¤±æ•—" + +#: add-patch.c +msgid "No changes." +msgstr "沒有更動。" + +#: add-patch.c +msgid "Only binary files changed." +msgstr "åªæœ‰äºŒé€²ä½æª”案更動了。" #: advice.c #, c-format @@ -746,7 +767,7 @@ msgid "" "Disable this message with \"git config advice.%s false\"" msgstr "" "\n" -"請使用 “git config advice.%s false†åœç”¨æ¤è¨Šæ¯" +"請使用「git config advice.%s falseã€åœç”¨æ¤è¨Šæ¯" #: advice.c #, c-format @@ -782,7 +803,7 @@ msgid "" "Fix them up in the work tree, and then use 'git add/rm <file>'\n" "as appropriate to mark resolution and make a commit." msgstr "" -"請在工作å€ä¿®æ£æª”案,然後視情æ³ä½¿ç”¨ “git add/rm <file>â€\n" +"請在工作å€ä¿®æ£æª”案,然後視情æ³ä½¿ç”¨ã€Œgit add/rm <file>ã€\n" "命令標記解決方案並æäº¤ã€‚" #: advice.c @@ -866,7 +887,7 @@ msgid "" "false\n" "\n" msgstr "" -"註:切æ›è‡³ “%sâ€ã€‚\n" +"註:切æ›è‡³ã€Œ%sã€ã€‚\n" "\n" "您æ£è™•於「分離 HEADã€ç‹€æ…‹ã€‚您å¯ä»¥æª¢è¦–ã€é€²è¡Œå¯¦é©—性修改並æäº¤ï¼Œ\n" "而且您å¯ä»¥åœ¨åˆ‡å›žåˆ†æ”¯æ™‚ï¼Œæ¨æ£„在æ¤ç‹€æ…‹ä¸‹æ‰€åšçš„æäº¤\n" @@ -901,8 +922,8 @@ msgid "" "* Use \"git sparse-checkout reapply\" to apply the sparsity rules" msgstr "" "è‹¥è¦æ›´æ£é€™äº›è·¯å¾‘的稀ç–狀態,請:\n" -"* 使用 “git add --sparse <路徑†更新索引\n" -"* 使用 “git sparse-checkout reapply†套用稀ç–è¦å‰‡" +"* 使用「git add --sparse <路徑>ã€æ›´æ–°ç´¢å¼•\n" +"* 使用「git sparse-checkout reapplyã€å¥—用稀ç–è¦å‰‡" #: alias.c msgid "cmdline ends with \\" @@ -913,19 +934,19 @@ msgid "unclosed quote" msgstr "未閉åˆçš„引號" #: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c -#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c msgid "too many arguments" msgstr "引數éŽå¤š" #: apply.c #, c-format msgid "unrecognized whitespace option '%s'" -msgstr "空白å—å…ƒé¸é … “%s†無法è˜åˆ¥" +msgstr "空白å—å…ƒé¸é …「%sã€ç„¡æ³•è˜åˆ¥" #: apply.c #, c-format msgid "unrecognized whitespace ignore option '%s'" -msgstr "空白å—元忽略é¸é … “%s†無法è˜åˆ¥" +msgstr "空白å—元忽略é¸é …「%sã€ç„¡æ³•è˜åˆ¥" #: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c #: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c @@ -939,12 +960,12 @@ msgstr "空白å—元忽略é¸é … “%s†無法è˜åˆ¥" #: range-diff.c revision.c #, c-format msgid "options '%s' and '%s' cannot be used together" -msgstr "ç„¡æ³•åŒæ™‚使用 “%s†和 “%s†é¸é …" +msgstr "ç„¡æ³•åŒæ™‚使用「%sã€å’Œã€Œ%sã€é¸é …" #: apply.c #, c-format msgid "'%s' outside a repository" -msgstr "“%s†在版本庫之外" +msgstr "「%sã€åœ¨ç‰ˆæœ¬åº«ä¹‹å¤–" #: apply.c msgid "failed to read patch" @@ -1080,7 +1101,7 @@ msgstr "ç„¡æ³•é–‹å•Ÿæˆ–è®€å– %s" #: apply.c #, c-format msgid "invalid start of line: '%c'" -msgstr "無效的列首å—元:“%câ€" +msgstr "無效的列首å—元:「%cã€" #: apply.c #, c-format @@ -1105,43 +1126,43 @@ msgstr "" #: apply.c #, c-format msgid "missing binary patch data for '%s'" -msgstr "缺少 “%s†的二進ä½ä¿®è£œæª”資料" +msgstr "缺少「%sã€çš„二進ä½ä¿®è£œæª”資料" #: apply.c #, c-format msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" -msgstr "無法åå‘套用一個缺少至 “%s†的åå‘資料å€å¡Šçš„二進ä½ä¿®è£œæª”" +msgstr "無法åå‘套用一個缺少至「%sã€çš„åå‘資料å€å¡Šçš„二進ä½ä¿®è£œæª”" #: apply.c #, c-format msgid "cannot apply binary patch to '%s' without full index line" -msgstr "無法在 “%s†上套用沒有完整索引列的二進ä½ä¿®è£œæª”" +msgstr "無法在「%sã€ä¸Šå¥—用沒有完整索引列的二進ä½ä¿®è£œæª”" #: apply.c #, c-format msgid "" "the patch applies to '%s' (%s), which does not match the current contents." -msgstr "修補檔è¦å¥—用到 “%sâ€ï¼ˆ%s),但與目å‰å…§å®¹ä¸ç¬¦ã€‚" +msgstr "修補檔è¦å¥—用到「%sã€ï¼ˆ%s),但與目å‰å…§å®¹ä¸ç¬¦ã€‚" #: apply.c #, c-format msgid "the patch applies to an empty '%s' but it is not empty" -msgstr "修補檔è¦å¥—用至空檔案 “%sâ€ï¼Œä½†å…¶éžç©ºæª”案" +msgstr "修補檔è¦å¥—用至空檔案「%sã€ï¼Œä½†å…¶éžç©ºæª”案" #: apply.c #, c-format msgid "the necessary postimage %s for '%s' cannot be read" -msgstr "ç„¡æ³•è®€å– â€œ%2$sâ€ å¿…é ˆçš„ç›®æ¨™æª”æ¡ˆ %1$s" +msgstr "無法讀å–「%2$sã€å¿…é ˆçš„ç›®æ¨™æª”æ¡ˆ %1$s" #: apply.c #, c-format msgid "binary patch does not apply to '%s'" -msgstr "二進ä½ä¿®è£œæª”未套用到 “%sâ€" +msgstr "二進ä½ä¿®è£œæª”未套用到「%sã€" #: apply.c #, c-format msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" -msgstr "修補 “%s†的二進ä½ä¿®è£œæª”ï¼Œç”¢ç”Ÿäº†ä¸æ£ç¢ºçš„çµæžœï¼ˆé 期 %s,å»ç‚º %s)" +msgstr "修補「%sã€çš„二進ä½ä¿®è£œæª”ï¼Œç”¢ç”Ÿäº†ä¸æ£ç¢ºçš„çµæžœï¼ˆé 期 %s,å»ç‚º %s)" #: apply.c #, c-format @@ -1161,7 +1182,7 @@ msgstr "ç„¡æ³•è®€å– %s" #: apply.c #, c-format msgid "reading from '%s' beyond a symbolic link" -msgstr "讀å–符號連çµèƒŒå¾Œçš„ “%sâ€" +msgstr "讀å–符號連çµèƒŒå¾Œçš„「%sã€" #: apply.c #, c-format @@ -1190,7 +1211,7 @@ msgstr "æ£åœ¨é€²è¡Œä¸‰æ–¹åˆä½µâ€¦â€¦\n" #: apply.c #, c-format msgid "cannot read the current contents of '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%s†目å‰çš„內容" +msgstr "無法讀å–「%sã€ç›®å‰çš„內容" #: apply.c #, c-format @@ -1200,12 +1221,12 @@ msgstr "無法進行三方åˆä½µâ€¦â€¦\n" #: apply.c #, c-format msgid "Applied patch to '%s' with conflicts.\n" -msgstr "å·²å¥—ç”¨å° â€œ%s†的修補檔,但有è¡çªã€‚\n" +msgstr "已套用å°ã€Œ%sã€çš„修補檔,但有è¡çªã€‚\n" #: apply.c #, c-format msgid "Applied patch to '%s' cleanly.\n" -msgstr "å·²å®Œå…¨å¥—ç”¨å° â€œ%s†的修補檔。\n" +msgstr "已完全套用å°ã€Œ%sã€çš„修補檔。\n" #: apply.c #, c-format @@ -1229,7 +1250,7 @@ msgstr "%s 的類型是 %oï¼Œé æœŸæ˜¯ %o" #: apply.c read-cache.c #, c-format msgid "invalid path '%s'" -msgstr "路徑 “%s†無效" +msgstr "路徑「%sã€ç„¡æ•ˆ" #: apply.c #, c-format @@ -1254,7 +1275,7 @@ msgstr "%2$s 的新模å¼ï¼ˆ%1$o)和 %4$s 的舊模å¼ï¼ˆ%3$o)ä¸ç¬¦" #: apply.c #, c-format msgid "affected file '%s' is beyond a symbolic link" -msgstr "å—影響的檔案 “%s†在符號連çµå¾Œ" +msgstr "å—影響的檔案「%sã€åœ¨ç¬¦è™Ÿé€£çµå¾Œ" #: apply.c #, c-format @@ -1304,7 +1325,7 @@ msgstr "修補 %s 忍¡çµ„的修補檔æå£ž" #: apply.c #, c-format msgid "unable to stat newly created file '%s'" -msgstr "無法å°å‰›å»ºç«‹çš„æª”案 “%s†執行 stat" +msgstr "無法å°å‰›å»ºç«‹çš„æª”案「%sã€åŸ·è¡Œ stat" #: apply.c #, c-format @@ -1319,17 +1340,17 @@ msgstr "無法為 %s åŠ å…¥å¿«å–é …ç›®" #: apply.c builtin/bisect.c builtin/gc.c #, c-format msgid "failed to write to '%s'" -msgstr "無法寫入 “%sâ€" +msgstr "無法寫入「%sã€" #: apply.c #, c-format msgid "closing file '%s'" -msgstr "關閉檔案 “%sâ€" +msgstr "關閉檔案「%sã€" #: apply.c #, c-format msgid "unable to write file '%s' mode %o" -msgstr "ç„¡æ³•ä»¥æ¨¡å¼ %2$o 寫入 “%1$s†檔案" +msgstr "ç„¡æ³•ä»¥æ¨¡å¼ %2$o 寫入「%1$sã€æª”案" #: apply.c #, c-format @@ -1354,7 +1375,7 @@ msgstr "無法開啟 %s" #: apply.c rerere.c #, c-format msgid "cannot unlink '%s'" -msgstr "無法刪除 “%sâ€" +msgstr "無法刪除「%sã€" #: apply.c #, c-format @@ -1369,11 +1390,11 @@ msgstr "拒絕第 #%d 個å€å¡Šã€‚" #: apply.c #, c-format msgid "Skipped patch '%s'." -msgstr "ç•¥éŽä¿®è£œæª” “%sâ€ã€‚" +msgstr "ç•¥éŽä¿®è£œæª”「%sã€ã€‚" #: apply.c msgid "No valid patches in input (allow with \"--allow-empty\")" -msgstr "輸入沒有有效的修補檔內容(傳入 “--allow-empty†å…許æ¤è¡Œç‚ºï¼‰" +msgstr "輸入沒有有效的修補檔內容(傳入「--allow-emptyã€å…許æ¤è¡Œç‚ºï¼‰" #: apply.c t/helper/test-cache-tree.c msgid "unable to read index file" @@ -1382,7 +1403,7 @@ msgstr "無法讀å–索引檔案" #: apply.c #, c-format msgid "can't open patch '%s': %s" -msgstr "無法開啟修補檔 “%sâ€ï¼š%s" +msgstr "無法開啟修補檔「%sã€ï¼š%s" #: apply.c #, c-format @@ -1466,6 +1487,18 @@ msgstr "亦套用修補檔(與 --stat/--summary/--check é¸é …åŒæ™‚使用)" msgid "attempt three-way merge, fall back on normal patch if that fails" msgstr "嘗試三方åˆä½µï¼Œè‹¥å¤±æ•—則回到æ£å¸¸ä¿®è£œæ¨¡å¼" +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "如果è¡çªï¼Œä½¿ç”¨æˆ‘們的版本" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "如果è¡çªï¼Œä½¿ç”¨ä»–們的版本" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "如果è¡çªï¼Œä½¿ç”¨è¯åˆç‰ˆæœ¬" + #: apply.c msgid "build a temporary index based on embedded index information" msgstr "組建以嵌入索引資訊為基礎的暫å˜ç´¢å¼•" @@ -1527,6 +1560,10 @@ msgstr "在所有檔案å稱å‰åŠ ä¸Š <root>" msgid "don't return error for empty patches" msgstr "é‡åˆ°ç©ºç™½ä¿®è£œæª”時,ä¸å›žå‚³éŒ¯èª¤" +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "--oursã€--theirs å’Œ --union éœ€è¦ --3way" + #: archive-tar.c archive-zip.c #, c-format msgid "cannot stream blob %s" @@ -1545,7 +1582,7 @@ msgstr "壓縮錯誤 (%d)" #: archive-tar.c #, c-format msgid "unable to start '%s' filter" -msgstr "無法啟動 “%sâ€ éŽæ¿¾å™¨" +msgstr "無法啟動「%sã€éŽæ¿¾å™¨" #: archive-tar.c msgid "unable to redirect descriptor" @@ -1554,7 +1591,7 @@ msgstr "ç„¡æ³•é‡æ–°å°Žå‘æè¿°å…ƒ" #: archive-tar.c #, c-format msgid "'%s' filter reported error" -msgstr "“%sâ€ éŽæ¿¾å™¨å›žå ±éŒ¯èª¤" +msgstr "「%sã€éŽæ¿¾å™¨å›žå ±éŒ¯èª¤" #: archive-zip.c #, c-format @@ -1588,17 +1625,17 @@ msgstr "git archive --remote <repo> [--exec <cmd>] --list" #: archive.c builtin/gc.c builtin/notes.c builtin/tag.c #, c-format msgid "cannot read '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%sâ€" +msgstr "無法讀å–「%sã€" #: archive.c #, c-format msgid "pathspec '%s' matches files outside the current directory" -msgstr "符åˆè·¯å¾‘è¦æ ¼ “%s†的檔案在目å‰ç›®éŒ„之外" +msgstr "符åˆè·¯å¾‘è¦æ ¼ã€Œ%sã€çš„æª”案在目å‰ç›®éŒ„之外" #: archive.c builtin/add.c builtin/rm.c #, c-format msgid "pathspec '%s' did not match any files" -msgstr "è·¯å¾‘è¦æ ¼ “%s†未符åˆä»»ä½•檔案" +msgstr "è·¯å¾‘è¦æ ¼ã€Œ%sã€æœªç¬¦åˆä»»ä½•檔案" #: archive.c #, c-format @@ -1617,6 +1654,11 @@ msgstr "éžæ¨¹ç‹€ç‰©ä»¶ï¼š%s" #: archive.c #, c-format +msgid "failed to unpack tree object %s" +msgstr "解包 %s 樹狀物件失敗" + +#: archive.c +#, c-format msgid "File not found: %s" msgstr "找ä¸åˆ°æª”案:%s" @@ -1628,17 +1670,17 @@ msgstr "䏿˜¯ä¸€èˆ¬æª”案:%s" #: archive.c #, c-format msgid "unclosed quote: '%s'" -msgstr "未閉åˆçš„引號:“%sâ€" +msgstr "未閉åˆçš„引號:「%sã€" #: archive.c #, c-format msgid "missing colon: '%s'" -msgstr "缺少冒號:“%sâ€" +msgstr "缺少冒號:「%sã€" #: archive.c #, c-format msgid "empty file name: '%s'" -msgstr "檔案å稱空白:“%sâ€" +msgstr "檔案å稱空白:「%sã€" #: archive.c msgid "fmt" @@ -1725,26 +1767,26 @@ msgstr "éžé 期é¸é … --remote" #: revision.c #, c-format msgid "the option '%s' requires '%s'" -msgstr "“%s†é¸é …éœ€è¦ â€œ%sâ€" +msgstr "「%sã€é¸é …需è¦ã€Œ%sã€" #: archive.c msgid "Unexpected option --output" msgstr "éžé 期é¸é … --output" -#: archive.c +#: archive.c t/unit-tests/unit-test.c #, c-format msgid "extra command line parameter '%s'" -msgstr "å¤šå‡ºå‘½ä»¤åˆ—åƒæ•¸ “%sâ€" +msgstr "å¤šå‡ºå‘½ä»¤åˆ—åƒæ•¸ã€Œ%sã€" #: archive.c #, c-format msgid "Unknown archive format '%s'" -msgstr "å°å˜æ ¼å¼ “%s†未知" +msgstr "å°å˜æ ¼å¼ã€Œ%sã€æœªçŸ¥" #: archive.c #, c-format msgid "Argument not supported for format '%s': -%d" -msgstr "å¼•æ•¸ä¸æ”¯æ´ “%sâ€ æ ¼å¼ï¼š-%d" +msgstr "å¼•æ•¸ä¸æ”¯æ´ã€Œ%sã€æ ¼å¼ï¼š-%d" #: attr.c #, c-format @@ -1771,22 +1813,26 @@ msgid "" "Use '\\!' for literal leading exclamation." msgstr "" "git attributes 會忽略å呿¨¡å¼\n" -"ç•¶å—串確定è¦ä»¥é©šå˜†è™Ÿé–‹å§‹æ™‚,請使用 “\\!â€ã€‚" +"ç•¶å—串確定è¦ä»¥é©šå˜†è™Ÿé–‹å§‹æ™‚,請使用「\\!ã€ã€‚" #: attr.c #, c-format msgid "cannot fstat gitattributes file '%s'" -msgstr "無法 fstat gitattributes 檔案 “%sâ€" +msgstr "無法 fstat gitattributes 檔案「%sã€" #: attr.c #, c-format msgid "ignoring overly large gitattributes file '%s'" -msgstr "忽略éŽå¤§çš„ gitattributes 檔案 “%sâ€" +msgstr "忽略éŽå¤§çš„ gitattributes 檔案「%sã€" #: attr.c #, c-format msgid "ignoring overly large gitattributes blob '%s'" -msgstr "忽略éŽå¤§çš„ gitattributes 資料物件 “%sâ€" +msgstr "忽略éŽå¤§çš„ gitattributes 資料物件「%sã€" + +#: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "沒有版本庫無法使用 --attr-source 或 GIT_ATTR_SOURCE" #: attr.c msgid "bad --attr-source or GIT_ATTR_SOURCE" @@ -1795,18 +1841,18 @@ msgstr "無效的 --attr-source 或 GIT_ATTR_SOURCE" #: attr.c read-cache.c #, c-format msgid "unable to stat '%s'" -msgstr "ç„¡æ³•å° %s 執行 stat" +msgstr "無法統計「%sã€" #: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c -#: builtin/pack-objects.c combine-diff.c rerere.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c #, c-format msgid "unable to read %s" -msgstr "ä¸èƒ½è®€ %s" +msgstr "ç„¡æ³•è®€å– %s" #: bisect.c #, c-format msgid "Badly quoted content in file '%s': %s" -msgstr "檔案 “%s†包å«ç„¡æ•ˆçš„引用內容:%s" +msgstr "檔案「%sã€åŒ…å«ç„¡æ•ˆçš„引用內容:%s" #: bisect.c #, c-format @@ -1843,7 +1889,7 @@ msgid "" "This means the first '%s' commit is between %s and [%s].\n" msgstr "" "åˆä½µåŸºç¤Ž %s 是 %s。\n" -"這æ„味著第一個 “%s†æäº¤ä½æ–¼ %s å’Œ [%s] 之間。\n" +"這æ„味著第一個「%sã€æäº¤ä½æ–¼ %s å’Œ [%s] 之間。\n" #: bisect.c #, c-format @@ -1880,17 +1926,17 @@ msgstr "需è¦ä¸€å€‹ %s 修訂版" #: bisect.c #, c-format msgid "could not create file '%s'" -msgstr "無法建立 “%s†檔案" +msgstr "無法建立「%sã€æª”案" #: bisect.c builtin/notes.c #, c-format msgid "unable to start 'show' for object '%s'" -msgstr "ä¸èƒ½ç‚ºç‰©ä»¶ '%s' é–‹å§‹ 'show'" +msgstr "無法為物件「%sã€é–‹å§‹ã€Œshowã€" #: bisect.c builtin/merge.c #, c-format msgid "could not read file '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%s†檔案" +msgstr "無法讀å–「%sã€æª”案" #: bisect.c msgid "reading bisect refs failed" @@ -1933,7 +1979,7 @@ msgstr "--contents å’Œ --reverse ä¸èƒ½æ··ç”¨ã€‚" msgid "--reverse and --first-parent together require specified latest commit" msgstr "--reverse å’Œ --first-parent å…±ç”¨ï¼Œéœ€è¦æŒ‡å®šæœ€æ–°çš„æäº¤" -#: blame.c builtin/commit.c builtin/log.c builtin/merge.c +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c #: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c #: remote.c sequencer.c submodule.c msgid "revision walk setup failed" @@ -1963,22 +2009,22 @@ msgstr "請求é‡å®šåŸºåº•時,無法繼承多個引用的上游追蹤è¨å®š" #: branch.c #, c-format msgid "not setting branch '%s' as its own upstream" -msgstr "未將 “%s†分支è¨ç‚ºå…¶è‡ªå·±çš„上游" +msgstr "未將「%sã€åˆ†æ”¯è¨ç‚ºå…¶è‡ªå·±çš„上游" #: branch.c #, c-format msgid "branch '%s' set up to track '%s' by rebasing." -msgstr "已藉由é‡è¨‚基底,將 “%s†分支è¨å®šç‚ºè¿½è¹¤ “%sâ€ã€‚" +msgstr "已藉由é‡è¨‚基底,將「%sã€åˆ†æ”¯è¨å®šç‚ºè¿½è¹¤ã€Œ%sã€ã€‚" #: branch.c #, c-format msgid "branch '%s' set up to track '%s'." -msgstr "已將 “%s†分支è¨å®šç‚ºè¿½è¹¤ “%sâ€ã€‚" +msgstr "已將「%sã€åˆ†æ”¯è¨å®šç‚ºè¿½è¹¤ã€Œ%sã€ã€‚" #: branch.c #, c-format msgid "branch '%s' set up to track:" -msgstr "“%s†分支已è¨å®šè¿½è¹¤ï¼š" +msgstr "「%sã€åˆ†æ”¯å·²è¨å®šè¿½è¹¤ï¼š" #: branch.c msgid "unable to write upstream branch configuration" @@ -1997,25 +2043,23 @@ msgstr "" #: branch.c #, c-format msgid "asked to inherit tracking from '%s', but no remote is set" -msgstr "請求繼承 “%s†的追蹤è¨å®šï¼Œä½†æœªè¨å®šé 端" +msgstr "請求繼承「%sã€çš„追蹤è¨å®šï¼Œä½†æœªè¨å®šé 端" #: branch.c #, c-format msgid "asked to inherit tracking from '%s', but no merge configuration is set" -msgstr "請求繼承 “%s†的追蹤è¨å®šï¼Œä½†æœªè¨å®šåˆä½µè¨å®š" +msgstr "請求繼承「%sã€çš„追蹤è¨å®šï¼Œä½†æœªè¨å®šåˆä½µè¨å®š" #: branch.c #, c-format msgid "not tracking: ambiguous information for ref '%s'" -msgstr "未追蹤:“%s†引用有æ§ç¾©" +msgstr "未追蹤:「%sã€å¼•用有æ§ç¾©" # è¯è€…:為ä¿è‰åœ¨è¼¸å‡ºä¸å°é½Šï¼Œæ³¨æ„調整å¥ä¸ç©ºæ ¼ï¼ -#. #-#-#-#-# branch.c.po #-#-#-#-# #. TRANSLATORS: This is a line listing a remote with duplicate #. refspecs in the advice message below. For RTL languages you'll #. probably want to swap the "%s" and leading " " space around. #. -#. #-#-#-#-# object-name.c.po #-#-#-#-# #. TRANSLATORS: This is line item of ambiguous object output #. from describe_ambiguous_object() above. For RTL languages #. you'll probably want to swap the "%s" and leading " " space @@ -2042,7 +2086,7 @@ msgid "" "tracking namespaces." msgstr "" "有多個é 端的抓å–å¼•ç”¨è¦æ ¼ï¼Œæ˜ 射到\n" -"é 端追蹤引用 “%sâ€ çš„è¦æ ¼ï¼š\n" +"é 端追蹤引用「%sã€çš„è¦æ ¼ï¼š\n" "%s\n" "這通常是è¨å®šéŒ¯èª¤ã€‚\n" "\n" @@ -2052,7 +2096,7 @@ msgstr "" #: branch.c #, c-format msgid "'%s' is not a valid branch name" -msgstr "“%sâ€ ä¸æ˜¯æœ‰æ•ˆçš„分支å稱" +msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„分支å稱" #: branch.c builtin/branch.c msgid "See `man git check-ref-format`" @@ -2061,22 +2105,22 @@ msgstr "è«‹åƒé–±ã€Œman git check-ref-formatã€" #: branch.c #, c-format msgid "a branch named '%s' already exists" -msgstr "已有åŒå “%s†分支" +msgstr "已有åŒå「%sã€åˆ†æ”¯" #: branch.c #, c-format msgid "cannot force update the branch '%s' used by worktree at '%s'" -msgstr "ç„¡æ³•å¼·åˆ¶æ›´æ–°è¢«ä½æ–¼ “%2$s†的工作å€ä½¿ç”¨çš„ “%1$s†分支" +msgstr "ç„¡æ³•å¼·åˆ¶æ›´æ–°è¢«ä½æ–¼ã€Œ%2$sã€çš„工作å€ä½¿ç”¨çš„分支「%1$sã€" #: branch.c #, c-format msgid "cannot set up tracking information; starting point '%s' is not a branch" -msgstr "無法è¨å®šè¿½è¹¤è³‡è¨Šï¼šèµ·å§‹é»ž “%sâ€ ä¸æ˜¯åˆ†æ”¯" +msgstr "無法è¨å®šè¿½è¹¤è³‡è¨Šï¼šèµ·å§‹é»žã€Œ%sã€ä¸æ˜¯åˆ†æ”¯" #: branch.c #, c-format msgid "the requested upstream branch '%s' does not exist" -msgstr "請求的上游分支 “%s†ä¸å˜åœ¨" +msgstr "請求的上游分支「%sã€ä¸å˜åœ¨" #: branch.c msgid "" @@ -2100,22 +2144,22 @@ msgstr "" #: branch.c builtin/replace.c #, c-format msgid "not a valid object name: '%s'" -msgstr "物件å稱無效:“%sâ€" +msgstr "物件å稱無效:「%sã€" #: branch.c #, c-format msgid "ambiguous object name: '%s'" -msgstr "物件å稱有æ§ç¾©ï¼šâ€œ%sâ€" +msgstr "物件å稱有æ§ç¾©ï¼šã€Œ%sã€" #: branch.c #, c-format msgid "not a valid branch point: '%s'" -msgstr "分支點無效:“%sâ€" +msgstr "分支點無效:「%sã€" #: branch.c #, c-format msgid "submodule '%s': unable to find submodule" -msgstr "“%sâ€ åæ¨¡çµ„:找ä¸åˆ°å模組" +msgstr "「%sã€å模組:找ä¸åˆ°å模組" #: branch.c #, c-format @@ -2123,18 +2167,18 @@ msgid "" "You may try updating the submodules using 'git checkout --no-recurse-" "submodules %s && git submodule update --init'" msgstr "" -"您å¯ä»¥ä½¿ç”¨ “git checkout --no-recurse-submodules %s && git submodule update " -"--initâ€ å‘½ä»¤å˜—è©¦æ›´æ–°åæ¨¡çµ„" +"您å¯ä»¥ä½¿ç”¨ã€Œgit checkout --no-recurse-submodules %s && git submodule update " +"--initã€å‘½ä»¤å˜—è©¦æ›´æ–°åæ¨¡çµ„" #: branch.c #, c-format msgid "submodule '%s': cannot create branch '%s'" -msgstr "“%sâ€ åæ¨¡çµ„:無法建立 “%s†分支" +msgstr "「%sã€å模組:無法建立「%sã€åˆ†æ”¯" #: branch.c #, c-format msgid "'%s' is already used by worktree at '%s'" -msgstr "“%sâ€ å·²è¢«ä½æ–¼ “%s†的工作å€ä½¿ç”¨" +msgstr "「%sã€å·²è¢«ä½æ–¼ã€Œ%sã€çš„工作å€ä½¿ç”¨" #: builtin/add.c msgid "git add [<options>] [--] <pathspec>..." @@ -2150,14 +2194,6 @@ msgid "Unstaged changes after refreshing the index:" msgstr "釿–°æ•´ç†ç´¢å¼•之後,尚未被暫å˜çš„æ›´å‹•:" #: builtin/add.c -msgid "" -"the add.interactive.useBuiltin setting has been removed!\n" -"See its entry in 'git help config' for details." -msgstr "" -"add.interactive.useBuiltin è¨å®šå·²è¢«ç§»é™¤ï¼\n" -"深入了解請åƒé–± “git help config†ä¸çš„å°æ‡‰æ¢ç›®ã€‚" - -#: builtin/add.c msgid "could not read the index" msgstr "無法讀å–索引" @@ -2168,7 +2204,7 @@ msgstr "編輯修補檔失敗" #: builtin/add.c read-cache.c #, c-format msgid "could not stat '%s'" -msgstr "ä¸èƒ½å° '%s' å‘¼å« stat" +msgstr "無法統計「%sã€" #: builtin/add.c msgid "empty patch. aborted" @@ -2177,7 +2213,7 @@ msgstr "ä¿®è£œæª”ç©ºç™½ã€‚ä¸æ¢" #: builtin/add.c #, c-format msgid "could not apply '%s'" -msgstr "無法套用 “%sâ€" +msgstr "無法套用「%sã€" #: builtin/add.c msgid "The following paths are ignored by one of your .gitignore files:\n" @@ -2191,7 +2227,7 @@ msgstr "測試執行" #: builtin/add.c builtin/check-ignore.c builtin/commit.c #: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c -#: builtin/read-tree.c +#: builtin/read-tree.c builtin/refs.c msgid "be verbose" msgstr "詳細輸出" @@ -2284,7 +2320,7 @@ msgstr "" "\n" "\tgit rm --cached %s\n" "\n" -"åƒè¦‹ “git help submodule†深入了解。" +"åƒè¦‹ã€Œgit help submoduleã€æ·±å…¥äº†è§£ã€‚" #: builtin/add.c #, c-format @@ -2293,7 +2329,7 @@ msgstr "æ£åœ¨åŠ å…¥åµŒå…¥å¼ git 版本庫:%s" #: builtin/add.c msgid "Use -f if you really want to add them." -msgstr "如果您確定想è¦åŠ å…¥ä»–å€‘ï¼Œè«‹ä½¿ç”¨ã€Œ-fã€ã€‚" +msgstr "如果您確定想è¦åŠ å…¥å®ƒå€‘ï¼Œè«‹ä½¿ç”¨ -f。" #: builtin/add.c msgid "adding files failed" @@ -2302,13 +2338,13 @@ msgstr "åŠ å…¥æª”æ¡ˆå¤±æ•—" #: builtin/add.c #, c-format msgid "--chmod param '%s' must be either -x or +x" -msgstr "--chmod çš„åƒæ•¸ “%sâ€ å¿…é ˆæ˜¯ -x 或 +x" +msgstr "--chmod çš„åƒæ•¸ã€Œ%sã€å¿…é ˆæ˜¯ -x 或 +x" #: builtin/add.c builtin/checkout.c builtin/commit.c builtin/reset.c #: builtin/rm.c builtin/stash.c #, c-format msgid "'%s' and pathspec arguments cannot be used together" -msgstr "“%sâ€ å’Œè·¯å¾‘è¦æ ¼å¼•數ä¸å¾—åŒæ™‚使用" +msgstr "「%sã€å’Œè·¯å¾‘è¦æ ¼å¼•數ä¸å¾—åŒæ™‚使用" #: builtin/add.c #, c-format @@ -2334,19 +2370,19 @@ msgstr "無法寫入新的索引檔案" #: builtin/am.c builtin/mailinfo.c mailinfo.c #, c-format msgid "bad action '%s' for '%s'" -msgstr "“%sâ€ å‹•ä½œå° â€œ%s†無效" +msgstr "「%sã€å‹•作å°ã€Œ%sã€ç„¡æ•ˆ" #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c #: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c #: ls-refs.c parallel-checkout.c sequencer.c setup.c #, c-format msgid "invalid value for '%s': '%s'" -msgstr "“%s†的值無效:“%sâ€" +msgstr "「%sã€çš„值無效:「%sã€" #: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c #, c-format msgid "could not read '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%sâ€" +msgstr "無法讀å–「%sã€" #: builtin/am.c msgid "could not parse author script" @@ -2360,17 +2396,17 @@ msgstr "ç„¡æ³•è§£æž %s" #: builtin/am.c #, c-format msgid "'%s' was deleted by the applypatch-msg hook" -msgstr "“%s†被 applypatch-msg 掛鉤刪除" +msgstr "「%sã€è¢« applypatch-msg 掛鉤刪除" #: builtin/am.c #, c-format msgid "Malformed input line: '%s'." -msgstr "æ ¼å¼éŒ¯èª¤çš„輸入列:“%sâ€ã€‚" +msgstr "æ ¼å¼éŒ¯èª¤çš„輸入列:「%sã€ã€‚" #: builtin/am.c #, c-format msgid "Failed to copy notes from '%s' to '%s'" -msgstr "從 “%s†拷è²è¨»è§£åˆ° “%s†失敗" +msgstr "從「%sã€æ‹·è²è¨»è§£åˆ°ã€Œ%sã€å¤±æ•—" #: builtin/am.c msgid "fseek failed" @@ -2379,17 +2415,17 @@ msgstr "fseek 失敗" #: builtin/am.c builtin/rebase.c sequencer.c wrapper.c #, c-format msgid "could not open '%s' for reading" -msgstr "無法開啟 “%s†進行讀å–" +msgstr "無法開啟「%sã€é€²è¡Œè®€å–" #: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c #, c-format msgid "could not open '%s' for writing" -msgstr "無法開啟 “%s†進行寫入" +msgstr "無法開啟「%sã€é€²è¡Œå¯«å…¥" #: builtin/am.c #, c-format msgid "could not parse patch '%s'" -msgstr "無法解æžä¿®è£œæª” “%sâ€" +msgstr "無法解æžä¿®è£œæª”「%sã€" #: builtin/am.c msgid "Only one StGIT patch series can be applied at once" @@ -2414,7 +2450,7 @@ msgstr "ä¿®è£œæª”æ ¼å¼åµæ¸¬å¤±æ•—。" #: builtin/am.c builtin/clone.c #, c-format msgid "failed to create directory '%s'" -msgstr "無法建立目錄 “%sâ€" +msgstr "無法建立目錄「%sã€" #: builtin/am.c msgid "Failed to split patches." @@ -2439,7 +2475,7 @@ msgstr "è‹¥è¦å°‡ç©ºç™½ä¿®è£œæª”錄入為空白æäº¤ï¼Œè«‹åŸ·è¡Œã€Œ%s --allow-e #: builtin/am.c #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." -msgstr "è‹¥è¦é‚„åŽŸè‡³åŽŸå§‹åˆ†æ”¯ï¼Œä¸¦åœæ¢ä¿®è£œå‹•作,請執行 “%s --abortâ€ã€‚" +msgstr "è‹¥è¦é‚„åŽŸè‡³åŽŸå§‹åˆ†æ”¯ï¼Œä¸¦åœæ¢ä¿®è£œå‹•作,請執行「%s --abortã€ã€‚" #: builtin/am.c msgid "Patch sent with format=flowed; space at the end of lines might be lost." @@ -2554,7 +2590,7 @@ msgstr "在 %s %.*s 處修補失敗" #: builtin/am.c msgid "Use 'git am --show-current-patch=diff' to see the failed patch" -msgstr "使用 “git am --show-current-patch=diff†命令檢視失敗的修補檔" +msgstr "使用「git am --show-current-patch=diffã€å‘½ä»¤æª¢è¦–失敗的修補檔" #: builtin/am.c msgid "No changes - recorded it as an empty commit." @@ -2566,7 +2602,7 @@ msgid "" "If there is nothing left to stage, chances are that something else\n" "already introduced the same changes; you might want to skip this patch." msgstr "" -"沒有變更:是å¦å¿˜è¨˜åŸ·è¡Œ “git addâ€ï¼Ÿ\n" +"沒有變更:是å¦å¿˜è¨˜åŸ·è¡Œã€Œgit addã€ï¼Ÿ\n" "å¦‚æžœæ²’æœ‰å…¶ä»–è¦æ–°å¢žåˆ°æš«å˜å€çš„,則很å¯èƒ½æ˜¯å…¶å®ƒæäº¤\n" "已經引入了相åŒçš„變更。您也許想è¦ç•¥éŽé€™å€‹ä¿®è£œæª”。" @@ -2584,7 +2620,7 @@ msgstr "" #: builtin/am.c builtin/reset.c #, c-format msgid "Could not parse object '%s'." -msgstr "ç„¡æ³•è§£æž â€œ%s†物件。" +msgstr "無法解æžã€Œ%sã€ç‰©ä»¶ã€‚" #: builtin/am.c msgid "failed to clean index" @@ -2595,13 +2631,13 @@ msgid "" "You seem to have moved HEAD since the last 'am' failure.\n" "Not rewinding to ORIG_HEAD" msgstr "" -"您似乎在上一次 “am†失敗後移動了 HEAD。\n" +"您似乎在上一次「amã€å¤±æ•—後移動了 HEAD。\n" "未倒轉回 ORIG_HEAD" -#: builtin/am.c builtin/bisect.c worktree.c +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c #, c-format msgid "failed to read '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%sâ€" +msgstr "無法讀å–「%sã€" #: builtin/am.c msgid "git am [<options>] [(<mbox> | <Maildir>)...]" @@ -2676,8 +2712,8 @@ msgstr "n" #: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c #: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c -#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c -#: builtin/verify-tag.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c msgid "format" msgstr "format" @@ -2714,6 +2750,10 @@ msgid "show the patch being applied" msgstr "顯示æ£åœ¨å¥—用的修補檔" #: builtin/am.c +msgid "try to apply current patch again" +msgstr "冿¬¡å˜—試套用目å‰ä¿®è£œæª”" + +#: builtin/am.c msgid "record the empty patch as an empty commit" msgstr "將空白修補檔錄入為空白æäº¤" @@ -2766,7 +2806,7 @@ msgid "" "Use \"git am --abort\" to remove it." msgstr "" "發ç¾å¤±æ•£çš„ %s 目錄。\n" -"使用 “git am --abort†移除。" +"使用「git am --abortã€ç§»é™¤ã€‚" #: builtin/am.c msgid "Resolve operation not in progress, we are not resuming." @@ -2785,10 +2825,6 @@ msgid "could not redirect output" msgstr "ç„¡æ³•é‡æ–°å°Žå‘輸出" #: builtin/archive.c -msgid "git archive: Remote with no URL" -msgstr "git archive: 未æä¾›é 端 URL" - -#: builtin/archive.c msgid "git archive: expected ACK/NAK, got a flush packet" msgstr "git archiveï¼šé æœŸæ˜¯ ACK/NAKï¼Œå»æ”¶åˆ° flush å°åŒ…" @@ -2836,32 +2872,32 @@ 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 msgid "can't use the builtin command '%s' as a term" -msgstr "ä¸èƒ½å°‡å…§å»ºå‘½ä»¤ “%s†當作術語使用" +msgstr "ä¸èƒ½å°‡å…§å»ºå‘½ä»¤ã€Œ%sã€ç•¶ä½œè¡“語使用" #: builtin/bisect.c #, c-format msgid "can't change the meaning of the term '%s'" -msgstr "ä¸èƒ½è®Šæ›´è¡“語 “%s†的å«ç¾©" +msgstr "ä¸èƒ½è®Šæ›´è¡“語「%sã€çš„å«ç¾©" #: builtin/bisect.c msgid "please use two different terms" @@ -2875,13 +2911,13 @@ msgstr "我們沒有在二分æœå°‹ã€‚\n" #: builtin/bisect.c #, c-format msgid "'%s' is not a valid commit" -msgstr "“%sâ€ ä¸æ˜¯æœ‰æ•ˆçš„æäº¤" +msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„æäº¤" #: builtin/bisect.c #, 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 @@ -2891,12 +2927,12 @@ msgstr "bisect_write 引數無效:%s" #: builtin/bisect.c #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "無法å–得修訂版 “%s†的物件 ID" +msgstr "無法å–得修訂版「%sã€çš„物件 ID" #: builtin/bisect.c #, c-format msgid "couldn't open the file '%s'" -msgstr "無法開啟檔案 “%sâ€" +msgstr "無法開啟檔案「%sã€" #: builtin/bisect.c #, c-format @@ -2910,7 +2946,7 @@ msgid "" "You can use \"git bisect %s\" and \"git bisect %s\" for that." msgstr "" "需指定至少一個 %s 和一個 %s 修訂版。\n" -"ç‚ºæ¤æ‚¨å¯ä»¥ç”¨ “git bisect %s†和 “git bisect %sâ€ã€‚" +"ç‚ºæ¤æ‚¨å¯ä»¥ç”¨ã€Œgit bisect %sã€å’Œã€Œgit bisect %sã€ã€‚" #: builtin/bisect.c #, c-format @@ -2919,9 +2955,9 @@ msgid "" "You then need to give me at least one %s and %s revision.\n" "You can use \"git bisect %s\" and \"git bisect %s\" for that." msgstr "" -"è¦é–‹å§‹ï¼Œè«‹åŸ·è¡Œ “git bisect startâ€ã€‚\n" +"è¦é–‹å§‹ï¼Œè«‹åŸ·è¡Œã€Œgit bisect startã€ã€‚\n" "接著æä¾›è‡³å°‘一個 %s 和一個 %s 修訂版。\n" -"ç‚ºæ¤æ‚¨å¯ä»¥ç”¨ “git bisect %s†和 “git bisect %sâ€ã€‚" +"ç‚ºæ¤æ‚¨å¯ä»¥ç”¨ã€Œgit bisect %sã€å’Œã€Œgit bisect %sã€ã€‚" #: builtin/bisect.c #, c-format @@ -2970,31 +3006,27 @@ msgid "" "invalid argument %s for 'git bisect terms'.\n" "Supported options are: --term-good|--term-old and --term-bad|--term-new." msgstr "" -"傳入 “git bisect terms†的 %s 引數無效。\n" +"傳入「git bisect termsã€çš„ %s 引數無效。\n" "支æ´çš„é¸é …有:--term-good|--term-old å’Œ --term-bad|--term-new。" #: builtin/bisect.c -msgid "revision walk setup failed\n" -msgstr "ä¿®è¨‚ç‰ˆéæ·è¨å®šå¤±æ•—\n" - -#: builtin/bisect.c #, c-format msgid "could not open '%s' for appending" -msgstr "無法開啟 “%sâ€ é€²è¡Œé™„åŠ " +msgstr "無法開啟「%sã€é€²è¡Œé™„åŠ " #: builtin/bisect.c msgid "'' is not a valid term" -msgstr "“ â€ ä¸æ˜¯æœ‰æ•ˆè¡“語" +msgstr "「 ã€ä¸æ˜¯æœ‰æ•ˆè¡“語" #: builtin/bisect.c #, c-format msgid "unrecognized option: '%s'" -msgstr "無法è˜åˆ¥é¸é …:“%sâ€" +msgstr "無法è˜åˆ¥é¸é …:「%sã€" #: builtin/bisect.c #, c-format msgid "'%s' does not appear to be a valid revision" -msgstr "“%sâ€ ä¼¼ä¹Žä¸æ˜¯æœ‰æ•ˆä¿®è¨‚版" +msgstr "「%sã€ä¼¼ä¹Žä¸æ˜¯æœ‰æ•ˆä¿®è¨‚版" #: builtin/bisect.c msgid "bad HEAD - I need a HEAD" @@ -3003,7 +3035,7 @@ msgstr "HEAD 無效 — 需è¦ä¸€å€‹ HEAD" #: builtin/bisect.c #, c-format msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'." -msgstr "簽出 “%s†失敗。請嘗試 “git bisect start <valid-branch>â€ã€‚" +msgstr "簽出「%sã€å¤±æ•—。請嘗試「git bisect start <valid-branch>ã€ã€‚" #: builtin/bisect.c msgid "bad HEAD - strange symbolic ref" @@ -3012,11 +3044,11 @@ msgstr "HEAD 無效 — 異常符號引用" #: builtin/bisect.c #, c-format msgid "invalid ref: '%s'" -msgstr "引用無效:“%sâ€" +msgstr "引用無效:「%sã€" #: builtin/bisect.c msgid "You need to start by \"git bisect start\"\n" -msgstr "è¦é–‹å§‹ï¼Œè«‹åŸ·è¡Œ “git bisect startâ€\n" +msgstr "è¦é–‹å§‹ï¼Œè«‹åŸ·è¡Œã€Œgit bisect startã€\n" # è¯è€…ï¼šè«‹ç¶æŒå¥å°¾ç©ºæ ¼ #. TRANSLATORS: Make sure to include [Y] and [n] in your @@ -3034,7 +3066,7 @@ msgstr "è¦å‘¼å« `--bisect-state`,請傳入一個以上的引數" #: builtin/bisect.c #, c-format msgid "'git bisect %s' can take only one argument." -msgstr "“git bisect %s†åªå–一個引數。" +msgstr "「git bisect %sã€åªå–一個引數。" #: builtin/bisect.c #, c-format @@ -3087,7 +3119,7 @@ msgstr "二分æœå°‹åŸ·è¡Œå¤±æ•—:%2$s å›žå‚³çš„çµæŸä»£ç¢¼ %1$d å°æ–¼ 0 或å #: builtin/bisect.c #, c-format msgid "cannot open file '%s' for writing" -msgstr "無法開啟 “%s†檔案進行寫入" +msgstr "無法開啟「%sã€æª”案進行寫入" #: builtin/bisect.c msgid "bisect run cannot continue any more" @@ -3104,22 +3136,22 @@ msgstr "二分æœå°‹ç™¼ç¾åˆ°ç¬¬ä¸€å€‹æœ‰å•題的æäº¤" #: builtin/bisect.c #, c-format msgid "bisect run failed: 'git bisect %s' exited with error code %d" -msgstr "二分æœå°‹åŸ·è¡Œå¤±æ•—:“git bisect %s†以錯誤碼 %d 離開" +msgstr "二分æœå°‹åŸ·è¡Œå¤±æ•—:「git bisect %sã€ä»¥éŒ¯èª¤ç¢¼ %d 離開" #: builtin/bisect.c #, c-format msgid "'%s' requires either no argument or a commit" -msgstr "“%s†ä¸éœ€è¦å¼•數,或者得傳入一個æäº¤" +msgstr "「%sã€ä¸éœ€è¦å¼•數,或者得傳入一個æäº¤" #: builtin/bisect.c #, c-format msgid "'%s' requires 0 or 1 argument" -msgstr "“%sâ€ éœ€è¦ 0 或 1 個引數" +msgstr "「%sã€éœ€è¦ 0 或 1 個引數" #: builtin/bisect.c #, c-format msgid "'%s' requires 0 arguments" -msgstr "“%s†ä¸éœ€å¼•數" +msgstr "「%sã€ä¸éœ€å¼•數" #: builtin/bisect.c msgid "no logfile given" @@ -3128,7 +3160,7 @@ msgstr "未æä¾›æ—¥èªŒæª”案" #: builtin/bisect.c #, c-format msgid "'%s' failed: no command provided." -msgstr "“%s†失敗:沒有æä¾›å‘½ä»¤ã€‚" +msgstr "「%sã€å¤±æ•—:沒有æä¾›å‘½ä»¤ã€‚" #: builtin/bisect.c msgid "need a command" @@ -3137,7 +3169,7 @@ msgstr "éœ€è¦æä¾›å‘½ä»¤" #: builtin/bisect.c builtin/cat-file.c #, c-format msgid "unknown command: '%s'" -msgstr "未知命令:“%sâ€" +msgstr "未知命令:「%sã€" #: builtin/blame.c msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>" @@ -3352,8 +3384,8 @@ msgid "" "deleting branch '%s' that has been merged to\n" " '%s', but not yet merged to HEAD" msgstr "" -"å°‡è¦åˆªé™¤çš„ “%s†分支已經被åˆä½µåˆ°\n" -" “%sâ€ï¼Œä½†å°šæœªåˆä½µåˆ° HEAD" +"å°‡è¦åˆªé™¤çš„分支「%sã€å·²ç¶“被åˆä½µåˆ°\n" +" 「%sã€ï¼Œä½†å°šæœªåˆä½µåˆ° HEAD" # è¯è€…ï¼šä¿æŒåŽŸæ›è¡Œæ ¼å¼ï¼Œåœ¨è¼¸å‡ºæ™‚ %s 的替代內容會讓å—串變長 #: builtin/branch.c @@ -3362,23 +3394,23 @@ msgid "" "not deleting branch '%s' that is not yet merged to\n" " '%s', even though it is merged to HEAD" msgstr "" -"並未刪除分支 “%sâ€ï¼Œ 雖然已經åˆä½µåˆ° HEAD,\n" -" å»å°šæœªè¢«åˆä½µè‡³ “%s†分支" +"並未刪除分支「%sã€ï¼Œé›–然已經åˆä½µåˆ° HEAD,\n" +" å»å°šæœªè¢«åˆä½µè‡³ã€Œ%sã€åˆ†æ”¯" #: builtin/branch.c #, c-format msgid "couldn't look up commit object for '%s'" -msgstr "無法查詢 “%s†指å‘çš„æäº¤ç‰©ä»¶" +msgstr "無法查詢「%sã€æŒ‡å‘çš„æäº¤ç‰©ä»¶" #: builtin/branch.c #, c-format msgid "the branch '%s' is not fully merged" -msgstr "分支 “%s†沒有完全åˆä½µ" +msgstr "分支「%sã€æ²’有完全åˆä½µ" #: builtin/branch.c #, c-format msgid "If you are sure you want to delete it, run 'git branch -D %s'" -msgstr "如果確定è¦åˆªé™¤å®ƒï¼Œè«‹åŸ·è¡Œ “git branch -D %sâ€" +msgstr "如果確定è¦åˆªé™¤å®ƒï¼Œè«‹åŸ·è¡Œã€Œgit branch -D %sã€" #: builtin/branch.c msgid "update of config-file failed" @@ -3391,12 +3423,12 @@ msgstr "ä¸èƒ½å°‡ -a å’Œ -d åŒæ™‚使用" #: builtin/branch.c #, c-format msgid "cannot delete branch '%s' used by worktree at '%s'" -msgstr "ç„¡æ³•åˆªé™¤è¢«ä½æ–¼ “%2$s†的工作å€ä½¿ç”¨çš„ “%1$s†分支" +msgstr "ç„¡æ³•åˆªé™¤è¢«ä½æ–¼ã€Œ%2$sã€çš„工作å€ä½¿ç”¨çš„分支「%1$sã€" #: builtin/branch.c #, c-format msgid "remote-tracking branch '%s' not found" -msgstr "找ä¸åˆ° “%s†é 端追蹤分支" +msgstr "找ä¸åˆ°é 端追蹤分支「%sã€" #: builtin/branch.c #, c-format @@ -3404,13 +3436,13 @@ msgid "" "branch '%s' not found.\n" "Did you forget --remote?" msgstr "" -"找ä¸åˆ° “%s†分支。\n" -"您å¯èƒ½è¦åŠ ä¸Š --remote?" +"找ä¸åˆ°åˆ†æ”¯ã€Œ%sã€ã€‚\n" +"您å¯èƒ½æƒ³åŠ ä¸Š --remote?" #: builtin/branch.c #, c-format msgid "branch '%s' not found" -msgstr "找ä¸åˆ° “%s†分支" +msgstr "找ä¸åˆ°åˆ†æ”¯ã€Œ%sã€" #: builtin/branch.c #, c-format @@ -3428,42 +3460,42 @@ msgstr "ç„¡æ³•è§£æžæ ¼å¼åŒ–å—串" #: builtin/branch.c msgid "could not resolve HEAD" -msgstr "ç„¡æ³•è§£æž HEAD 指é‡" +msgstr "ç„¡æ³•è§£æž HEAD 指標" #: builtin/branch.c #, c-format msgid "HEAD (%s) points outside of refs/heads/" -msgstr "HEAD æŒ‡é‡ (%s) æŒ‡å‘ refs/heads/ 之外" +msgstr "HEAD 指標 (%s) æŒ‡å‘ refs/heads/ 之外" #: builtin/branch.c #, c-format msgid "branch %s is being rebased at %s" -msgstr "%s 分支æ£åœ¨é‡å®šåŸºåº•至 %s" +msgstr "分支 %s æ£åœ¨é‡å®šåŸºåº•至 %s" #: builtin/branch.c #, c-format msgid "branch %s is being bisected at %s" -msgstr "%s åˆ†æ”¯æ£æ–¼ %s 進行二分æœå°‹" +msgstr "分支 %s æ£æ–¼ %s 進行二分æœå°‹" #: builtin/branch.c #, c-format msgid "HEAD of working tree %s is not updated" -msgstr "%s 工作å€çš„ HEAD æŒ‡é‡æœªè¢«æ›´æ–°" +msgstr "%s 工作å€çš„ HEAD 指標未被更新" #: builtin/branch.c #, c-format msgid "invalid branch name: '%s'" -msgstr "分支å稱無效:“%sâ€" +msgstr "分支å稱無效:「%sã€" #: builtin/branch.c #, c-format msgid "no commit on branch '%s' yet" -msgstr "分支 “%s†尚無æäº¤" +msgstr "分支「%sã€å°šç„¡æäº¤" #: builtin/branch.c #, c-format msgid "no branch named '%s'" -msgstr "沒有å為 “%s†的分支" +msgstr "沒有å為「%sã€çš„分支" #: builtin/branch.c msgid "branch rename failed" @@ -3476,17 +3508,17 @@ msgstr "分支拷è²å¤±æ•—" #: builtin/branch.c #, c-format msgid "created a copy of a misnamed branch '%s'" -msgstr "已為誤命åçš„ “%s†分支建立拷è²" +msgstr "已為誤命å的分支「%sã€å»ºç«‹æ‹·è²" #: builtin/branch.c #, c-format msgid "renamed a misnamed branch '%s' away" -msgstr "已更改誤命åçš„ “%s†分支的å稱" +msgstr "已更改誤命å的分支「%sã€çš„å稱" #: builtin/branch.c #, c-format msgid "branch renamed to %s, but HEAD is not updated" -msgstr "åˆ†æ”¯å·²é‡æ–°å‘½å為 %s,但 HEAD 指é‡å°šæœªæ›´æ–°" +msgstr "åˆ†æ”¯å·²é‡æ–°å‘½å為 %s,但 HEAD 指標尚未更新" #: builtin/branch.c msgid "branch is renamed, but update of config-file failed" @@ -3581,7 +3613,7 @@ msgstr "å³ä½¿ç›®æ¨™å·²å˜åœ¨ï¼Œä»ç§»å‹•æˆ–é‡æ–°å‘½å分支" #: builtin/branch.c builtin/for-each-ref.c builtin/tag.c msgid "do not output a newline after empty formatted refs" -msgstr "åœ¨æ ¼å¼åŒ–å¼•ç”¨çµæžœç‚ºç©ºä¹‹å¾Œï¼Œä¸è¦è¼¸å‡ºæ›åˆ—符號" +msgstr "åœ¨æ ¼å¼åŒ–çµæžœç‚ºç©ºçš„引用之後,ä¸è¦è¼¸å‡ºæ›åˆ—符號" #: builtin/branch.c msgid "copy a branch and its reflog" @@ -3650,7 +3682,7 @@ msgstr "無法將 HEAD è§£æžç‚ºæœ‰æ•ˆå¼•用" #: builtin/branch.c builtin/clone.c msgid "HEAD not found below refs/heads!" -msgstr "HEAD 指é‡ä¸åœ¨ /refs/heads ä¸ï¼" +msgstr "HEAD 指標ä¸åœ¨ /refs/heads ä¸ï¼" #: builtin/branch.c msgid "" @@ -3669,7 +3701,7 @@ msgstr "å¿…é ˆæä¾›åˆ†æ”¯å稱" #: builtin/branch.c msgid "cannot give description to detached HEAD" -msgstr "無法å‘分離 HEAD æŒ‡é‡æä¾›æè¿°" +msgstr "無法å‘分離 HEAD 指標æä¾›æè¿°" #: builtin/branch.c msgid "cannot edit description of more than one branch" @@ -3704,12 +3736,12 @@ msgstr "無法將 HEAD 的上游è¨ç‚º %s:其未指å‘任何分支" #: builtin/branch.c #, c-format msgid "no such branch '%s'" -msgstr "ç„¡ “%s†分支" +msgstr "無「%sã€åˆ†æ”¯" #: builtin/branch.c #, c-format msgid "branch '%s' does not exist" -msgstr "沒有 “%s†分支" +msgstr "沒有「%sã€åˆ†æ”¯" #: builtin/branch.c msgid "too many arguments to unset upstream" @@ -3722,21 +3754,22 @@ msgstr "ç„¡æ³•å–æ¶ˆè¨å®š HEAD 的上游:其未指å‘任何分支" #: builtin/branch.c #, c-format msgid "branch '%s' has no upstream information" -msgstr "分支 “%s†沒有上游資訊" +msgstr "分支「%sã€æ²’有上游資訊" #: builtin/branch.c msgid "" "the -a, and -r, options to 'git branch' do not take a branch name.\n" "Did you mean to use: -a|-r --list <pattern>?" msgstr "" -"“git branch†的 -a å’Œ -r é¸é …ä¸å–分支å稱。\n" +"「git branchã€çš„ -a å’Œ -r é¸é …ä¸å–分支å稱。\n" "您是想使用:-a|-r --list <pattern> 嗎?" #: builtin/branch.c msgid "" "the '--set-upstream' option is no longer supported. Please use '--track' or " "'--set-upstream-to' instead" -msgstr "ä¸å†æ”¯æ´é¸é … “--set-upstreamâ€ã€‚請改用 “--track†或 “--set-upstream-toâ€" +msgstr "" +"ä¸å†æ”¯æ´é¸é …「--set-upstreamã€ã€‚請改用「--trackã€æˆ–「--set-upstream-toã€" #: builtin/bugreport.c msgid "git version:\n" @@ -3745,7 +3778,7 @@ msgstr "git 版本:\n" #: builtin/bugreport.c #, c-format msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() 失敗,錯誤:“%s†(%d)\n" +msgstr "uname() 失敗,錯誤:「%sã€(%d)\n" #: builtin/bugreport.c msgid "compiler info: " @@ -3811,7 +3844,7 @@ msgstr "mode" #: builtin/bugreport.c msgid "" "create an additional zip archive of detailed diagnostics (default 'stats')" -msgstr "å¦å¤–建立有詳細診斷資訊的 ZIP å°å˜æª”(é è¨å€¼ “statsâ€ï¼‰" +msgstr "å¦å¤–建立有詳細診斷資訊的 ZIP å°å˜æª”(é è¨å€¼ã€Œstatsã€ï¼‰" #: builtin/bugreport.c msgid "specify a destination for the bugreport file(s)" @@ -3824,12 +3857,12 @@ msgstr "指定用於檔åçš„ strftime æ ¼å¼å¾Œç¶´" #: builtin/bugreport.c #, c-format msgid "unknown argument `%s'" -msgstr "未知引數 “%sâ€" +msgstr "未知引數「%sã€" #: builtin/bugreport.c builtin/diagnose.c #, c-format msgid "could not create leading directories for '%s'" -msgstr "無法建立 “%s†的å‰ç½®ç›®éŒ„" +msgstr "無法建立「%sã€çš„å‰ç½®ç›®éŒ„" #: builtin/bugreport.c builtin/diagnose.c #, c-format @@ -3852,7 +3885,7 @@ msgstr "無法寫入 %s" #: builtin/bugreport.c #, c-format msgid "Created new report at '%s'.\n" -msgstr "已在 “%sâ€ å»ºç«‹æ–°å ±å‘Šã€‚\n" +msgstr "已在「%sã€å»ºç«‹æ–°å ±å‘Šã€‚\n" #: builtin/bundle.c msgid "" @@ -3906,6 +3939,10 @@ msgstr "需è¦ç‰ˆæœ¬åº«ä¾†å»ºç«‹å¥—件包。" msgid "do not show bundle details" msgstr "ä¸é¡¯ç¤ºå¥—件包的詳細資訊" +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "需è¦ç‰ˆæœ¬åº«é©—è‰å¥—件包" + #: builtin/bundle.c #, c-format msgid "%s is okay\n" @@ -3922,7 +3959,7 @@ msgstr "æ£åœ¨æ‹†åˆ†ç‰©ä»¶" #: builtin/cat-file.c merge-recursive.c #, c-format msgid "cannot read object %s '%s'" -msgstr "無法讀å–物件 %s “%sâ€" +msgstr "無法讀å–物件 %s「%sã€" #: builtin/cat-file.c msgid "flush is only for --buffer mode" @@ -3935,7 +3972,7 @@ msgstr "è¼¸å…¥ä¸æ²’有命令" #: builtin/cat-file.c #, c-format msgid "whitespace before command: '%s'" -msgstr "命令剿œ‰ç©ºæ ¼ï¼šâ€œ%sâ€" +msgstr "命令剿œ‰ç©ºæ ¼ï¼šã€Œ%sã€" #: builtin/cat-file.c #, c-format @@ -4001,7 +4038,8 @@ msgstr "輸出 [æå£žçš„] ([broken]) 物件屬性" #: builtin/cat-file.c msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" -msgstr "顯示物件類型(å¯ä»¥æ˜¯ “blobâ€ã€â€œtreeâ€ã€â€œcommitâ€ã€â€œtag†ç‰å…¶ä¸ä¸€å€‹ï¼‰" +msgstr "" +"顯示物件類型(å¯ä»¥æ˜¯ã€Œblobã€ã€ã€Œtreeã€ã€ã€Œcommitã€ã€ã€Œtagã€ç‰å…¶ä¸ä¸€å€‹ï¼‰" #: builtin/cat-file.c msgid "show object size" @@ -4079,12 +4117,12 @@ msgstr "blob|tree" #: builtin/cat-file.c msgid "use a <path> for (--textconv | --filters); Not with 'batch'" -msgstr "請在 (--textconv | --filters) 使用 <path>ï¼Œè€Œéž â€œbatchâ€" +msgstr "請在 (--textconv | --filters) 使用 <path>,而éžã€Œbatchã€" #: builtin/cat-file.c #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" -msgstr "“%s=<%s>â€ éœ€è¦ â€œ%s†或 “%sâ€" +msgstr "「%s=<%s>ã€éœ€è¦ã€Œ%sã€æˆ–「%sã€" #: builtin/cat-file.c msgid "path|tree-ish" @@ -4093,12 +4131,12 @@ msgstr "path|tree-ish" #: builtin/cat-file.c #, c-format msgid "'%s' requires a batch mode" -msgstr "“%sâ€ éœ€è¦æ‰¹æ¬¡è™•ç†æ¨¡å¼" +msgstr "「%sã€éœ€è¦æ‰¹æ¬¡è™•ç†æ¨¡å¼" #: builtin/cat-file.c #, c-format msgid "'-%c' is incompatible with batch mode" -msgstr "“-%câ€ èˆ‡æ‰¹æ¬¡è™•ç†æ¨¡å¼ä¸ç›¸å®¹" +msgstr "「-%cã€èˆ‡æ‰¹æ¬¡è™•ç†æ¨¡å¼ä¸ç›¸å®¹" #: builtin/cat-file.c msgid "batch modes take no arguments" @@ -4107,12 +4145,12 @@ msgstr "æ‰¹æ¬¡è™•ç†æ¨¡å¼ä¸å–引數" #: builtin/cat-file.c #, c-format msgid "<rev> required with '%s'" -msgstr "“%sâ€ éœ€è¦ <rev>" +msgstr "「%sã€éœ€è¦ <rev>" #: builtin/cat-file.c #, c-format msgid "<object> required with '-%c'" -msgstr "“-%câ€ éœ€è¦ <object>" +msgstr "「-%cã€éœ€è¦ <object>" #: builtin/cat-file.c #, c-format @@ -4202,9 +4240,16 @@ msgid "also read contacts from stdin" msgstr "亦從 stdin 讀å–è¯çµ¡åœ°å€" #: builtin/check-mailmap.c -#, c-format -msgid "unable to parse contact: %s" -msgstr "無法解æžè¯çµ¡åœ°å€ï¼š%s" +msgid "read additional mailmap entries from file" +msgstr "從檔案讀å–å…¶ä»– mailmap é …ç›®" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "資料物件" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "從 blob 讀å–å…¶ä»– mailmap é …ç›®" #: builtin/check-mailmap.c msgid "no contacts specified" @@ -4286,32 +4331,32 @@ msgstr "git restore [<options>] [--source=<branch>] <file>..." #: builtin/checkout.c #, c-format msgid "path '%s' does not have our version" -msgstr "“%s†路徑沒有我們的版本" +msgstr "「%sã€è·¯å¾‘沒有我們的版本" #: builtin/checkout.c #, c-format msgid "path '%s' does not have their version" -msgstr "“%s†路徑沒有他們的版本" +msgstr "「%sã€è·¯å¾‘沒有他們的版本" #: builtin/checkout.c #, c-format msgid "path '%s' does not have all necessary versions" -msgstr "“%sâ€ è·¯å¾‘æ²’æœ‰æ‰€æœ‰å¿…é ˆçš„ç‰ˆæœ¬" +msgstr "「%sã€è·¯å¾‘æ²’æœ‰æ‰€æœ‰å¿…é ˆçš„ç‰ˆæœ¬" #: builtin/checkout.c #, c-format msgid "path '%s' does not have necessary versions" -msgstr "“%sâ€ è·¯å¾‘æ²’æœ‰å¿…é ˆçš„ç‰ˆæœ¬" +msgstr "「%sã€è·¯å¾‘æ²’æœ‰å¿…é ˆçš„ç‰ˆæœ¬" #: builtin/checkout.c #, c-format msgid "path '%s': cannot merge" -msgstr "path “%sâ€ï¼šç„¡æ³•åˆä½µ" +msgstr "path「%sã€ï¼šç„¡æ³•åˆä½µ" #: builtin/checkout.c #, c-format msgid "Unable to add merge result for '%s'" -msgstr "無法為 “%sâ€ åŠ ä¸Šåˆä½µçµæžœ" +msgstr "無法為「%sã€åŠ ä¸Šåˆä½µçµæžœ" #: builtin/checkout.c #, c-format @@ -4334,37 +4379,37 @@ msgstr[0] "å·²å¾žç´¢å¼•å€æ›´æ–° %d 個路徑" #: builtin/checkout.c #, c-format msgid "'%s' cannot be used with updating paths" -msgstr "無法在更新路徑時使用 “%sâ€" +msgstr "無法在更新路徑時使用「%sã€" #: builtin/checkout.c #, c-format msgid "Cannot update paths and switch to branch '%s' at the same time." -msgstr "ç„¡æ³•åŒæ™‚更新路徑和切æ›è‡³ “%s†分支。" +msgstr "ç„¡æ³•åŒæ™‚更新路徑和切æ›è‡³ã€Œ%sã€åˆ†æ”¯ã€‚" #: builtin/checkout.c #, c-format msgid "neither '%s' or '%s' is specified" -msgstr "“%s†或 “%s†皆未指定" +msgstr "「%sã€æˆ–「%sã€çš†æœªæŒ‡å®š" #: builtin/checkout.c #, c-format msgid "'%s' must be used when '%s' is not specified" -msgstr "未指定 “%2$sâ€ æ™‚ï¼Œå¿…é ˆä½¿ç”¨ “%1$sâ€" +msgstr "未指定「%2$sã€æ™‚ï¼Œå¿…é ˆä½¿ç”¨ã€Œ%1$sã€" #: builtin/checkout.c #, c-format msgid "'%s' or '%s' cannot be used with %s" -msgstr "“%s†或 “%s†無法與 %s 一起使用" +msgstr "「%sã€æˆ–「%sã€ç„¡æ³•與 %s 一起使用" #: builtin/checkout.c #, c-format msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree" -msgstr "“%sâ€ã€â€œ%s†或 “%s†無法在簽出樹狀物件時使用" +msgstr "「%sã€ã€ã€Œ%sã€æˆ–「%sã€ç„¡æ³•在簽出樹狀物件時使用" #: builtin/checkout.c #, c-format msgid "path '%s' is unmerged" -msgstr "路徑 “%s†未åˆä½µ" +msgstr "路徑「%sã€æœªåˆä½µ" #: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c #: merge-ort.c reset.c sequencer.c tree-walk.c @@ -4388,7 +4433,7 @@ msgstr "" #: builtin/checkout.c #, c-format msgid "Can not do reflog for '%s': %s\n" -msgstr "ç„¡æ³•å° â€œ%s†執行 reflog 動作:%s\n" +msgstr "無法å°ã€Œ%sã€åŸ·è¡Œ reflog 動作:%s\n" #: builtin/checkout.c msgid "HEAD is now at" @@ -4401,27 +4446,27 @@ msgstr "無法更新 HEAD" #: builtin/checkout.c #, c-format msgid "Reset branch '%s'\n" -msgstr "é‡è¨åˆ†æ”¯ “%sâ€\n" +msgstr "é‡è¨åˆ†æ”¯ã€Œ%sã€\n" #: builtin/checkout.c #, c-format msgid "Already on '%s'\n" -msgstr "å·²ç¶“ä½æ–¼ “%sâ€\n" +msgstr "å·²ç¶“ä½æ–¼ã€Œ%sã€\n" #: builtin/checkout.c #, c-format msgid "Switched to and reset branch '%s'\n" -msgstr "已切æ›ä¸¦é‡è¨åˆ†æ”¯ “%sâ€\n" +msgstr "已切æ›ä¸¦é‡è¨åˆ†æ”¯ã€Œ%sã€\n" #: builtin/checkout.c #, c-format msgid "Switched to a new branch '%s'\n" -msgstr "已切æ›è‡³æ–°åˆ†æ”¯ “%sâ€\n" +msgstr "已切æ›è‡³æ–°åˆ†æ”¯ã€Œ%sã€\n" #: builtin/checkout.c #, c-format msgid "Switched to branch '%s'\n" -msgstr "已切æ›è‡³åˆ†æ”¯ “%sâ€\n" +msgstr "已切æ›è‡³åˆ†æ”¯ã€Œ%sã€\n" # è¯è€…ï¼šè«‹ç¶æŒå‰å°Žç©ºæ ¼ #: builtin/checkout.c @@ -4474,7 +4519,7 @@ msgstr "åœ¨ä¿®è¨‚ç‰ˆéæ·æ™‚é‡åˆ°å…§éƒ¨éŒ¯èª¤" #: builtin/checkout.c msgid "Previous HEAD position was" -msgstr "之å‰çš„ HEAD 指é‡ä½ç½®åœ¨" +msgstr "之å‰çš„ HEAD 指標ä½ç½®åœ¨" #: builtin/checkout.c msgid "You are on a branch yet to be born" @@ -4486,7 +4531,7 @@ msgid "" "'%s' could be both a local file and a tracking branch.\n" "Please use -- (and optionally --no-guess) to disambiguate" msgstr "" -"“%s†既å¯ä»¥æ˜¯æœ¬æ©Ÿæª”案,也å¯ä»¥æ˜¯è¿½è¹¤åˆ†æ”¯ã€‚\n" +"「%sã€æ—¢å¯ä»¥æ˜¯æœ¬æ©Ÿæª”案,也å¯ä»¥æ˜¯è¿½è¹¤åˆ†æ”¯ã€‚\n" "請使用 --(和å¯é¸çš„ --no-guess)來消除æ§ç¾©" #: builtin/checkout.c @@ -4500,19 +4545,19 @@ msgid "" "one remote, e.g. the 'origin' remote, consider setting\n" "checkout.defaultRemote=origin in your config." msgstr "" -"如果您想è¦ç°½å‡ºé 端追蹤分支,例如 “originâ€ï¼Œ\n" +"如果您想è¦ç°½å‡ºé 端追蹤分支,例如「originã€ï¼Œ\n" "您å¯ä»¥ä½¿ç”¨ --track é¸é …寫出全å:\n" "\n" " git checkout --track origin/<name>\n" "\n" "如果您平時比較想è¦ä½¿ç”¨æ¨¡ç³Šçš„ç°¡çŸåˆ†æ”¯å稱 <name>,\n" -"而ä¸å¤ªæƒ³å¯«å¦‚ “origin†的é 端版本庫å稱,\n" +"而ä¸å¤ªæƒ³å¯«å¦‚「originã€çš„é 端版本庫å稱,\n" "å¯ä»¥åœ¨çµ„æ…‹ä¸è¨å®š checkout.defaultRemote=origin。" #: builtin/checkout.c #, c-format msgid "'%s' matched multiple (%d) remote tracking branches" -msgstr "“%s†符åˆå¤šå€‹ (%d) é 端追蹤分支" +msgstr "「%sã€ç¬¦åˆå¤šå€‹ (%d) é 端追蹤分支" #: builtin/checkout.c msgid "only one reference expected" @@ -4536,27 +4581,27 @@ msgstr "å¼•ç”¨ä¸æ˜¯æ¨¹ç‹€ç‰©ä»¶ï¼š%s" #: builtin/checkout.c #, c-format msgid "a branch is expected, got tag '%s'" -msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°æ¨™ç±¤ “%sâ€" +msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°æ¨™ç±¤ã€Œ%sã€" #: builtin/checkout.c #, c-format msgid "a branch is expected, got remote branch '%s'" -msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°é 端分支 “%sâ€" +msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°é 端分支「%sã€" #: builtin/checkout.c #, c-format msgid "a branch is expected, got '%s'" -msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ° “%sâ€" +msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°ã€Œ%sã€" #: builtin/checkout.c #, c-format msgid "a branch is expected, got commit '%s'" -msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°æäº¤ “%sâ€" +msgstr "é æœŸæ”¶åˆ°åˆ†æ”¯ï¼Œå»æ”¶åˆ°æäº¤ã€Œ%sã€" #: builtin/checkout.c msgid "" "If you want to detach HEAD at the commit, try again with the --detach option." -msgstr "若您想è¦åœ¨æ¤æäº¤åˆ†é›¢ HEAD 指é‡ï¼Œè«‹å‚³å…¥ --detach é¸é …é‡è©¦ã€‚" +msgstr "若您想è¦åœ¨æ¤æäº¤åˆ†é›¢ HEAD 指標,請傳入 --detach é¸é …é‡è©¦ã€‚" #: builtin/checkout.c msgid "" @@ -4564,7 +4609,7 @@ msgid "" "Consider \"git merge --quit\" or \"git worktree add\"." msgstr "" "無法在åˆä½µæ™‚切æ›åˆ†æ”¯\n" -"請試試 “git merge --quit†或 “git worktree addâ€ã€‚" +"請試試「git merge --quitã€æˆ–「git worktree addã€ã€‚" #: builtin/checkout.c msgid "" @@ -4572,7 +4617,7 @@ msgid "" "Consider \"git am --quit\" or \"git worktree add\"." msgstr "" "無法在 am 工作階段期間時切æ›åˆ†æ”¯\n" -"請試試 “git am --quit†或 “git worktree addâ€ã€‚" +"請試試「git am --quitã€æˆ–「git worktree addã€ã€‚" #: builtin/checkout.c msgid "" @@ -4580,7 +4625,7 @@ msgid "" "Consider \"git rebase --quit\" or \"git worktree add\"." msgstr "" "無法在é‡å®šåŸºåº•時切æ›åˆ†æ”¯\n" -"請試試 “git rebase --quit†或 “git worktree addâ€ã€‚" +"請試試「git rebase --quitã€æˆ–「git worktree addã€ã€‚" #: builtin/checkout.c msgid "" @@ -4588,7 +4633,7 @@ msgid "" "Consider \"git cherry-pick --quit\" or \"git worktree add\"." msgstr "" "無法在æ€é¸æ™‚切æ›åˆ†æ”¯\n" -"請試試 “git cherry-pick --quit†或 “git worktree addâ€ã€‚" +"請試試「git cherry-pick --quitã€æˆ–「git worktree addã€ã€‚" #: builtin/checkout.c msgid "" @@ -4596,7 +4641,7 @@ msgid "" "Consider \"git revert --quit\" or \"git worktree add\"." msgstr "" "無法在還原時切æ›åˆ†æ”¯\n" -"請試試 “git revert --quit†或 “git worktree addâ€ã€‚" +"請試試「git revert --quitã€æˆ–「git worktree addã€ã€‚" #: builtin/checkout.c msgid "you are switching branch while bisecting" @@ -4609,22 +4654,27 @@ msgstr "路徑ä¸èƒ½èˆ‡åˆ‡æ›åˆ†æ”¯åŒæ™‚使用" #: builtin/checkout.c #, c-format msgid "'%s' cannot be used with switching branches" -msgstr "“%s†ä¸èƒ½èˆ‡åˆ‡æ›åˆ†æ”¯åŒæ™‚使用" +msgstr "「%sã€ä¸èƒ½èˆ‡åˆ‡æ›åˆ†æ”¯åŒæ™‚使用" + +#: builtin/checkout.c +#, c-format +msgid "'%s' needs the paths to check out" +msgstr "「%sã€éœ€è¦æŒ‡å®šè¦ç°½å‡ºçš„路徑" #: builtin/checkout.c #, c-format msgid "'%s' cannot be used with '%s'" -msgstr "“%s†ä¸èƒ½èˆ‡ “%sâ€ åŒæ™‚使用" +msgstr "「%sã€ä¸èƒ½èˆ‡ã€Œ%sã€åŒæ™‚使用" #: builtin/checkout.c #, c-format msgid "'%s' cannot take <start-point>" -msgstr "“%s†ä¸å– <start-point>" +msgstr "「%sã€ä¸å– <start-point>" #: builtin/checkout.c #, c-format msgid "Cannot switch branch to a non-commit '%s'" -msgstr "無法將分支切æ›è‡³éžæäº¤é …ç›® “%sâ€" +msgstr "無法將分支切æ›è‡³éžæäº¤é …目「%sã€" #: builtin/checkout.c msgid "missing branch or commit argument" @@ -4649,7 +4699,7 @@ msgstr "è¡çªè¼¸å‡ºé¢¨æ ¼ï¼ˆmergeã€diff3 或 zdiff3)" #: builtin/checkout.c builtin/worktree.c msgid "detach HEAD at named commit" -msgstr "自指定æäº¤åˆ†é›¢ HEAD 指é‡" +msgstr "自指定æäº¤åˆ†é›¢ HEAD 指標" #: builtin/checkout.c msgid "force checkout (throw away local modifications)" @@ -4686,7 +4736,7 @@ msgstr "å°è·¯å¾‘è¦æ ¼ä¸åšç¨€ç–簽出的é™åˆ¶" #: builtin/checkout.c #, c-format msgid "options '-%c', '-%c', and '%s' cannot be used together" -msgstr "“-%câ€ã€â€œ-%c†和 “%s†é¸é …ä¸å¾—åŒæ™‚使用" +msgstr "「-%cã€ã€ã€Œ-%cã€å’Œã€Œ%sã€é¸é …ä¸å¾—åŒæ™‚使用" #: builtin/checkout.c msgid "--track needs a branch name" @@ -4709,12 +4759,12 @@ msgstr "ç„¡æ•ˆçš„è·¯å¾‘è¦æ ¼" #: builtin/checkout.c #, c-format msgid "'%s' is not a commit and a branch '%s' cannot be created from it" -msgstr "“%sâ€ ä¸æ˜¯æäº¤ï¼Œå› æ¤ä¸èƒ½ä»¥é€™ç‚ºåŸºç¤Žå»ºç«‹ “%s†分支" +msgstr "「%sã€ä¸æ˜¯æäº¤ï¼Œå› æ¤ä¸èƒ½ä»¥é€™ç‚ºåŸºç¤Žå»ºç«‹ã€Œ%sã€åˆ†æ”¯" #: builtin/checkout.c #, c-format msgid "git checkout: --detach does not take a path argument '%s'" -msgstr "git checkout:--detach ä¸å–路徑引數 “%sâ€" +msgstr "git checkout:--detach ä¸å–路徑引數「%sã€" #: builtin/checkout.c msgid "" @@ -4747,7 +4797,7 @@ msgstr "為新分支建立引用日誌" #: builtin/checkout.c msgid "second guess 'git checkout <no-such-branch>' (default)" -msgstr "二次猜測 “git checkout <ç„¡æ¤åˆ†æ”¯>â€ï¼ˆé è¨å€¼ï¼‰" +msgstr "二次猜測「git checkout <ç„¡æ¤åˆ†æ”¯>ã€ï¼ˆé è¨å€¼ï¼‰" #: builtin/checkout.c msgid "use overlay mode (default)" @@ -4763,7 +4813,7 @@ msgstr "建立/é‡è¨ä¸¦åˆ‡æ›è‡³æŒ‡å®šåˆ†æ”¯" #: builtin/checkout.c msgid "second guess 'git switch <no-such-branch>'" -msgstr "二次猜測 “git switch <ç„¡æ¤åˆ†æ”¯>â€" +msgstr "二次猜測「git switch <ç„¡æ¤åˆ†æ”¯>ã€" #: builtin/checkout.c msgid "throw away local modifications" @@ -4907,7 +4957,7 @@ msgstr "" "clean - 開始清ç†\n" "filter by pattern - é€éŽç¯„本排除è¦åˆªé™¤çš„æ¢ç›®\n" "select by numbers - é€éŽæ•¸å—鏿“‡è¦åˆªé™¤çš„æ¢ç›®\n" -"ask each - é‡å°åˆªé™¤é€ä¸€è©¢å•ï¼ˆå°±åƒ â€œrm -iâ€ï¼‰\n" +"ask each - é‡å°åˆªé™¤é€ä¸€è©¢å•(就åƒã€Œrm -iã€ï¼‰\n" "quit - åœæ¢åˆªé™¤ä¸¦é›¢é–‹\n" "help - 顯示本輔助說明\n" "? - 顯示如何在æç¤ºä¸‹é¸æ“‡çš„å”助" @@ -4937,9 +4987,9 @@ msgstr "äº’å‹•å¼æ¸…除" msgid "remove whole directories" msgstr "移除整個目錄" -#: builtin/clean.c builtin/describe.c builtin/grep.c builtin/log.c -#: builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c builtin/show-ref.c -#: ref-filter.h +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h msgid "pattern" msgstr "pattern" @@ -5027,7 +5077,7 @@ msgstr "name" #: builtin/clone.c msgid "use <name> instead of 'origin' to track upstream" -msgstr "使用 <name> è€Œä¸æ˜¯ “origin†追蹤上游" +msgstr "使用 <name> è€Œä¸æ˜¯ã€Œoriginã€è¿½è¹¤ä¸Šæ¸¸" #: builtin/clone.c msgid "checkout <branch> instead of the remote's HEAD" @@ -5078,7 +5128,7 @@ msgstr "gitdir" msgid "separate git dir from working tree" msgstr "git 目錄和工作å€åˆ†é›¢" -#: builtin/clone.c builtin/init-db.c +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c msgid "specify the reference format to use" msgstr "指定è¦ä½¿ç”¨çš„å¼•ç”¨æ ¼å¼" @@ -5138,7 +5188,7 @@ msgstr "%s å˜åœ¨ä¸”䏿˜¯ä¸€å€‹ç›®éŒ„" #: builtin/clone.c #, c-format msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "“%s†是個符號連çµï¼Œæ•…ä¸èƒ½ä½¿ç”¨ --local 複製" +msgstr "「%sã€æ˜¯å€‹ç¬¦è™Ÿé€£çµï¼Œæ•…ä¸èƒ½ä½¿ç”¨ --local 複製" #: builtin/clone.c #, c-format @@ -5153,7 +5203,17 @@ msgstr "「%sã€ç¬¦è™Ÿé€£çµå·²å˜åœ¨ï¼Œæ‹’絕使用 --local 複製" #: builtin/clone.c compat/precompose_utf8.c #, c-format msgid "failed to unlink '%s'" -msgstr "無法刪除 “%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 @@ -5165,7 +5225,7 @@ msgstr "å»ºç«‹é€£çµ '%s' 失敗" msgid "failed to copy file to '%s'" msgstr "複製檔案至 '%s' 失敗" -#: builtin/clone.c +#: builtin/clone.c refs/files-backend.c #, c-format msgid "failed to iterate over '%s'" msgstr "無法在 '%s' 上疊代" @@ -5231,10 +5291,11 @@ msgstr "å¤ªå¤šåƒæ•¸ã€‚" msgid "You must specify a repository to clone." msgstr "æ‚¨å¿…é ˆæŒ‡å®šè¦è¤‡è£½çš„版本庫。" -#: builtin/clone.c builtin/init-db.c setup.c +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c #, c-format msgid "unknown ref storage format '%s'" -msgstr "æœªçŸ¥çš„å¼•ç”¨å„²å˜æ ¼å¼ “%sâ€" +msgstr "æœªçŸ¥çš„å¼•ç”¨å„²å˜æ ¼å¼ã€Œ%sã€" #: builtin/clone.c #, c-format @@ -5331,7 +5392,7 @@ msgstr "無法åˆå§‹åŒ–版本庫,略éŽå¥—件包 URI" #: builtin/clone.c #, c-format msgid "failed to fetch objects from bundle URI '%s'" -msgstr "無法從套件包 URL “%s†抓å–物件" +msgstr "無法從套件包 URL「%sã€æŠ“å–物件" #: builtin/clone.c msgid "failed to fetch advertised bundles" @@ -5391,7 +5452,7 @@ msgstr "--command å¿…é ˆæ˜¯ç¬¬ä¸€å€‹åƒæ•¸" msgid "" "git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" msgstr "" -"git commit-graph verify [--object-dir <目錄>] [--shallow] [--[no-]progress]" +"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" #: builtin/commit-graph.c msgid "" @@ -5415,21 +5476,21 @@ msgstr "目錄" #: builtin/commit-graph.c msgid "the object directory to store the graph" -msgstr "儲å˜åœ–形的物件目錄" +msgstr "儲å˜åœ–的物件目錄" #: builtin/commit-graph.c msgid "if the commit-graph is split, only verify the tip file" -msgstr "如果æäº¤åœ–形被分割,åªé©—è‰é 一個檔案" +msgstr "如果æäº¤åœ–被分割,åªé©—è‰é 一個檔案" #: builtin/commit-graph.c #, c-format msgid "Could not open commit-graph '%s'" -msgstr "無法開啟æäº¤åœ–å½¢ '%s'" +msgstr "無法開啟æäº¤åœ–「%sã€" #: builtin/commit-graph.c #, c-format msgid "could not open commit-graph chain '%s'" -msgstr "無法開啟æäº¤åœ–éˆ â€œ%sâ€" +msgstr "無法開啟æäº¤åœ–éˆã€Œ%sã€" #: builtin/commit-graph.c #, c-format @@ -5465,7 +5526,7 @@ msgstr "從標準輸入ä¸çš„æäº¤é–‹å§‹æŽƒæ" #: builtin/commit-graph.c msgid "include all commits already in the commit-graph file" -msgstr "åŒ…å« commit-graph 檔案ä¸å·²æœ‰æ‰€æœ‰æäº¤" +msgstr "åŒ…å«æäº¤åœ–æª”æ¡ˆä¸æ‰€æœ‰å·²æœ‰çš„æäº¤" #: builtin/commit-graph.c msgid "enable computation for changed paths" @@ -5473,15 +5534,15 @@ msgstr "啟用已變更路徑的計算" #: builtin/commit-graph.c msgid "allow writing an incremental commit-graph file" -msgstr "å…è¨±å¯«ä¸€å€‹å¢žé‡æäº¤åœ–å½¢æª”æ¡ˆ" +msgstr "å…è¨±å¯«ä¸€å€‹å¢žé‡æäº¤åœ–æª”æ¡ˆ" #: builtin/commit-graph.c msgid "maximum number of commits in a non-base split commit-graph" -msgstr "在éžåŸºæœ¬åˆ†å‰²æäº¤åœ–å½¢ä¸çš„æœ€å¤§æäº¤æ•¸" +msgstr "在éžåŸºç¤Žåˆ†å‰²æäº¤åœ–ä¸çš„æœ€å¤§æäº¤æ•¸" #: builtin/commit-graph.c msgid "maximum ratio between two levels of a split commit-graph" -msgstr "一個分割æäº¤åœ–形的兩個級別之間的最大比率" +msgstr "一個分割æäº¤åœ–的兩個級別之間的最大比率" #: builtin/commit-graph.c msgid "only expire files older than a given date-time" @@ -5569,7 +5630,7 @@ msgstr "git commit-tree:讀å–失敗" msgid "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -5579,7 +5640,7 @@ msgid "" msgstr "" "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 <file> | -m <msg>] [--reset-author] [--allow-empty]\n" " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" @@ -5719,7 +5780,7 @@ msgstr "ç„¡æ³•é¸æ“‡ä¸€å€‹æœªè¢«ç›®å‰æäº¤èªªæ˜Žä½¿ç”¨çš„備註å—å…ƒ" #: builtin/commit.c #, c-format msgid "could not lookup commit '%s'" -msgstr "無法查詢æäº¤ “%sâ€" +msgstr "無法查詢æäº¤ã€Œ%sã€" #: builtin/commit.c builtin/shortlog.c #, c-format @@ -5845,7 +5906,7 @@ msgstr "%sæäº¤è€…:%.*s <%.*s>" msgid "Cannot read index" msgstr "無法讀å–索引" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "unable to pass trailers to --trailers" msgstr "無法將尾部署å傳éžè‡³ --trailers" @@ -6056,11 +6117,11 @@ msgstr "使用 autosquash æ ¼å¼çš„æäº¤èªªæ˜Žç”¨ä»¥å£“縮至指定的æäº¤" msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "ç¾åœ¨å°‡è©²æäº¤çš„作者改為我(和 -C/-c/--amend åƒæ•¸å…±ç”¨ï¼‰" -#: builtin/commit.c builtin/interpret-trailers.c +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c msgid "trailer" msgstr "尾部署å" -#: builtin/commit.c +#: builtin/commit.c builtin/tag.c msgid "add custom trailer(s)" msgstr "åŠ å…¥è‡ªè¨‚å°¾éƒ¨ç½²å" @@ -6169,20 +6230,68 @@ msgid "" "not exceeded, and then \"git restore --staged :/\" to recover." msgstr "" "版本庫已更新,但無法寫入新的索引檔案。請檢查ç£ç¢Ÿæ˜¯å¦\n" -"已滿或ç£ç¢Ÿé…é¡å·²è€—盡,然後執行 “git restore --staged :/†復原。" +"已滿或ç£ç¢Ÿé…é¡å·²è€—盡,然後執行「git restore --staged :/ã€å¾©åŽŸã€‚" #: builtin/config.c -msgid "git config [<options>]" -msgstr "git config [<é¸é …>]" +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "git config list [<檔案é¸é …>] [<顯示é¸é …>] [--includes]" #: builtin/config.c -#, c-format -msgid "unrecognized --type argument, %s" -msgstr "無法è˜åˆ¥çš„ --type åƒæ•¸ï¼Œ%s" +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"git config get [<檔案é¸é …>] [<顯示é¸é …>] [--includes] [--all] [--regexp] [--" +"value=<值>] [--fixed-value] [--default=<é è¨å€¼>] <å稱>" #: builtin/config.c -msgid "only one type at a time" -msgstr "一次åªèƒ½ä¸€å€‹é¡žåž‹" +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"git config set [<檔案é¸é …>] [--type=<類型>] [--all] [--value=<值>] [--fixed-" +"value] <å稱> <值>" + +#: builtin/config.c +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name> <value>" +msgstr "" +"git config unset [<檔案é¸é …>] [--all] [--value=<值>] [--fixed-value] <å稱> <" +"值>" + +#: builtin/config.c +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "git config rename-section [<檔案é¸é …>] <舊å稱> <æ–°å稱>" + +#: builtin/config.c +msgid "git config remove-section [<file-option>] <name>" +msgstr "git config remove-section [<檔案é¸é …>] <å稱>" + +#: builtin/config.c +msgid "git config edit [<file-option>]" +msgstr "git config edit [<檔案é¸é …>]" + +#: builtin/config.c +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" + +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"git config get [<檔案é¸é …>] [<顯示é¸é …>] [--includes] [--all] [--regexp=<常è¦" +"表示å¼>] [--value=<值>] [--fixed-value] [--default=<é è¨å€¼>] <å稱>" + +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"git config set [<檔案é¸é …>] [--type=<類型>] [--comment=<備註>] [--all] [--" +"value=<值>] [--fixed-value] <å稱> <值>" #: builtin/config.c msgid "Config file location" @@ -6217,70 +6326,6 @@ msgid "read config from given blob object" msgstr "從æä¾›çš„資料物件讀å–è¨å®š" #: builtin/config.c -msgid "Action" -msgstr "動作" - -#: builtin/config.c -msgid "get value: name [value-pattern]" -msgstr "å–得值:name [value-pattern]" - -#: builtin/config.c -msgid "get all values: key [value-pattern]" -msgstr "å–得所有值:key [value-pattern]" - -#: builtin/config.c -msgid "get values for regexp: name-regex [value-pattern]" -msgstr "æ ¹æ“šå¸¸è¦è¡¨ç¤ºå¼å–得值:name-regex [value-pattern]" - -#: builtin/config.c -msgid "get value specific for the URL: section[.var] URL" -msgstr "ç²å¾— URL å–值:section[.var] URL" - -#: builtin/config.c -msgid "replace all matching variables: name value [value-pattern]" -msgstr "å–代所有符åˆçš„變數:name value [value-pattern]" - -#: builtin/config.c -msgid "add a new variable: name value" -msgstr "新增一個新的變數:name value" - -#: builtin/config.c -msgid "remove a variable: name [value-pattern]" -msgstr "移除一個變數:name [value-pattern]" - -#: builtin/config.c -msgid "remove all matches: name [value-pattern]" -msgstr "移除所有符åˆé …目:name [value-pattern]" - -#: builtin/config.c -msgid "rename section: old-name new-name" -msgstr "釿–°å‘½åå°ç¯€ï¼šold-name new-name" - -#: builtin/config.c -msgid "remove a section: name" -msgstr "刪除一個å°ç¯€ï¼šname" - -#: builtin/config.c -msgid "list all" -msgstr "全部列出" - -#: builtin/config.c -msgid "use string equality when comparing values to 'value-pattern'" -msgstr "比較「value-patternã€çš„值時,使用å—ä¸²ç›¸ç‰æ¯”較" - -#: builtin/config.c -msgid "open an editor" -msgstr "開啟一個編輯器" - -#: builtin/config.c -msgid "find the color configured: slot [default]" -msgstr "ç²å¾—è¨å®šçš„é¡è‰²ï¼šè¨å®š [é è¨å€¼]" - -#: builtin/config.c -msgid "find the color setting: slot [stdout-is-tty]" -msgstr "ç²å¾—é¡è‰²è¨å®šï¼šè¨å®š [stdout-is-tty]" - -#: builtin/config.c msgid "Type" msgstr "類型" @@ -6317,8 +6362,8 @@ msgid "value is an expiry date" msgstr "值是一個到期日期" #: builtin/config.c -msgid "Other" -msgstr "其它" +msgid "Display options" +msgstr "顯示é¸é …" #: builtin/config.c msgid "terminate values with NUL byte" @@ -6329,10 +6374,6 @@ msgid "show variable names only" msgstr "åªé¡¯ç¤ºè®Šæ•¸å" #: builtin/config.c -msgid "respect include directives on lookup" -msgstr "查詢時引用 include 指令éžè¿´å°‹æ‰¾" - -#: builtin/config.c msgid "show origin of config (file, standard input, blob, command line)" msgstr "顯示è¨å®šçš„來æºï¼ˆæª”æ¡ˆã€æ¨™æº–輸入ã€è³‡æ–™ç‰©ä»¶ï¼Œæˆ–命令列)" @@ -6343,16 +6384,17 @@ msgstr "" "令 command)" #: builtin/config.c -msgid "value" -msgstr "å–值" +msgid "show config keys in addition to their values" +msgstr "除了顯示組態值,é¡å¤–顯示其éµå" #: builtin/config.c -msgid "with --get, use default value when missing entry" -msgstr "使用 --get ä½†æœªæŒ‡å®šåƒæ•¸æ™‚所使用的é è¨å€¼" +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "無法è˜åˆ¥çš„ --type åƒæ•¸ï¼Œ%s" #: builtin/config.c -msgid "human-readable comment string (# will be prepended as needed)" -msgstr "人類å¯è®€çš„備註å—串(將按需æ’å…¥ # è‡³å‰æ–¹ï¼‰" +msgid "only one type at a time" +msgstr "一次åªèƒ½ä¸€å€‹é¡žåž‹" #: builtin/config.c #, c-format @@ -6445,56 +6487,93 @@ msgstr "" "詳情請閱讀「git help worktreeã€çš„「CONFIGURATION FILEã€å°ç¯€" #: builtin/config.c -msgid "--get-color and variable type are incoherent" -msgstr "--get-color 和變數類型ä¸ç›¸å®¹" +msgid "Other" +msgstr "其它" #: builtin/config.c -msgid "only one action at a time" -msgstr "一次åªèƒ½æœ‰ä¸€å€‹å‹•作" +msgid "respect include directives on lookup" +msgstr "查詢時引用 include 指令éžè¿´å°‹æ‰¾" #: builtin/config.c -msgid "--name-only is only applicable to --list or --get-regexp" -msgstr "--name-only 僅é©ç”¨æ–¼ --list 或 --get-regexp" +#, c-format +msgid "unable to read config file '%s'" +msgstr "無法讀å–è¨å®šæª”案 '%s'" #: builtin/config.c -msgid "" -"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" -"list" -msgstr "--show-origin 僅é©ç”¨æ–¼ --getã€--get-allã€--get-regexp å’Œ --list" +msgid "error processing config file(s)" +msgstr "處ç†è¨å®šæª”案發生錯誤" #: builtin/config.c -msgid "--default is only applicable to --get" -msgstr "--default 僅é©ç”¨æ–¼ --get" +msgid "Filter options" +msgstr "éŽæ¿¾é¸é …" #: builtin/config.c -msgid "--comment is only applicable to add/set/replace operations" -msgstr "--comment åªèƒ½ç”¨æ–¼åŠ å…¥ã€è¨å®šå’Œå–代動作" +msgid "return all values for multi-valued config options" +msgstr "å›žå‚³æœ‰å¤šé …å€¼ä¹‹çµ„æ…‹é¸é …的所有值" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "å°‡å稱當作常è¦è¡¨ç¤ºå¼è§£è®€" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "é¡¯ç¤ºå€¼ç¬¦åˆæ¨¡å¼çš„組態" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" +msgstr "使用å—ä¸²ç›¸ç‰æ¯”較值和模å¼" + +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "é¡¯ç¤ºç¬¦åˆæä¾› URL 的組態" + +#: builtin/config.c +msgid "value" +msgstr "å–值" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "æœªæŒ‡å®šåƒæ•¸æ™‚所使用的é è¨å€¼" #: builtin/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value 僅套用至 'value-pattern'" #: builtin/config.c -#, c-format -msgid "unable to read config file '%s'" -msgstr "無法讀å–è¨å®šæª”案 '%s'" +msgid "--default= cannot be used with --all or --url=" +msgstr "--default= 無法和 --all 或 --url= 一起使用" #: builtin/config.c -msgid "error processing config file(s)" -msgstr "處ç†è¨å®šæª”案發生錯誤" +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "--url= 無法和 --allã€--regexpã€--value 一起使用" #: builtin/config.c -msgid "editing stdin is not supported" -msgstr "䏿”¯æ´ç·¨è¼¯æ¨™æº–輸入" +msgid "Filter" +msgstr "éŽæ¿¾å™¨" #: builtin/config.c -msgid "editing blobs is not supported" -msgstr "䏿”¯æ´ç·¨è¼¯è³‡æ–™ç‰©ä»¶" +msgid "replace multi-valued config option with new value" +msgstr "以新值å–ä»£æœ‰å¤šé …å€¼çš„çµ„æ…‹é¸é …" #: builtin/config.c -#, c-format -msgid "cannot create configuration file %s" -msgstr "ä¸èƒ½å»ºç«‹è¨å®šæª”案 %s" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "人類å¯è®€çš„備註å—串(將按需æ’å…¥ # è‡³å‰æ–¹ï¼‰" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "åœ¨ä¸æ›´å‹•ä»»ä½•ç¾æœ‰å€¼çš„æƒ…æ³ä¸‹æ–°å¢žä¸€è¡Œ" + +#: builtin/config.c +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "--fixed-value 僅套用至 --value=<模å¼>" + +#: builtin/config.c +msgid "--append cannot be used with --value=<pattern>" +msgstr "--append 無法和 --value=<模å¼> 一起使用" #: builtin/config.c #, c-format @@ -6510,6 +6589,109 @@ msgstr "" msgid "no such section: %s" msgstr "ç„¡æ¤å°ç¯€ï¼š%s" +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "䏿”¯æ´ç·¨è¼¯æ¨™æº–輸入" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "䏿”¯æ´ç·¨è¼¯è³‡æ–™ç‰©ä»¶" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "ä¸èƒ½å»ºç«‹è¨å®šæª”案 %s" + +#: builtin/config.c +msgid "Action" +msgstr "動作" + +#: builtin/config.c +msgid "get value: name [<value-pattern>]" +msgstr "å–得值:name [<value-pattern>]" + +#: builtin/config.c +msgid "get all values: key [<value-pattern>]" +msgstr "å–得所有值:key [<value-pattern>]" + +#: builtin/config.c +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "æ ¹æ“šå¸¸è¦è¡¨ç¤ºå¼å–得值:name-regex [<value-pattern>]" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "ç²å¾— URL å–值:section[.var] URL" + +#: builtin/config.c +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "å–代所有符åˆçš„變數:name value [<value-pattern>]" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "新增一個新的變數:name value" + +#: builtin/config.c +msgid "remove a variable: name [<value-pattern>]" +msgstr "移除一個變數:name [<value-pattern>]" + +#: builtin/config.c +msgid "remove all matches: name [<value-pattern>]" +msgstr "移除所有符åˆé …目:name [<value-pattern>]" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "釿–°å‘½åå°ç¯€ï¼šold-name new-name" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "刪除一個å°ç¯€ï¼šname" + +#: builtin/config.c +msgid "list all" +msgstr "全部列出" + +#: builtin/config.c +msgid "open an editor" +msgstr "開啟一個編輯器" + +#: builtin/config.c +msgid "find the color configured: slot [<default>]" +msgstr "ç²å¾—è¨å®šçš„é¡è‰²ï¼šè¨å®š [<é è¨å€¼>]" + +#: builtin/config.c +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "ç²å¾—é¡è‰²è¨å®šï¼šè¨å®š [<stdout-is-tty>]" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "使用 --get ä½†æœªæŒ‡å®šåƒæ•¸æ™‚所使用的é è¨å€¼" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "--get-color 和變數類型ä¸ç›¸å®¹" + +#: builtin/config.c +msgid "no action specified" +msgstr "未指定動作" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "--name-only 僅é©ç”¨æ–¼ --list 或 --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "--show-origin 僅é©ç”¨æ–¼ --getã€--get-allã€--get-regexp å’Œ --list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "--default 僅é©ç”¨æ–¼ --get" + +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "--comment åªèƒ½ç”¨æ–¼åŠ å…¥ã€è¨å®šå’Œå–代動作" + #: builtin/count-objects.c msgid "print sizes in human readable format" msgstr "以使用者å¯è®€çš„æ ¼å¼é¡¯ç¤ºå¤§å°" @@ -6694,11 +6876,11 @@ msgstr "標記" #: builtin/describe.c msgid "append <mark> on dirty working tree (default: \"-dirty\")" -msgstr "å°æ–¼é«’工作å€ï¼Œè¿½åŠ <標記>(é è¨å€¼ï¼šâ€-dirty\")" +msgstr "å°æ–¼é«’工作å€ï¼Œè¿½åŠ <標記>(é è¨å€¼ï¼šã€-dirty\")" #: builtin/describe.c msgid "append <mark> on broken working tree (default: \"-broken\")" -msgstr "å°æ–¼æå£žçš„工作å€ï¼Œè¿½åŠ <標記>(é è¨å€¼ï¼šâ€-broken\")" +msgstr "å°æ–¼æå£žçš„工作å€ï¼Œè¿½åŠ <標記>(é è¨å€¼ï¼šã€-broken\")" #: builtin/describe.c msgid "No names found, cannot describe anything." @@ -7113,8 +7295,8 @@ msgstr "" #: builtin/fetch.c #, c-format -msgid "%s did not send all necessary objects\n" -msgstr "%s æœªå‚³é€æ‰€æœ‰å¿…需的物件\n" +msgid "%s did not send all necessary objects" +msgstr "%s æœªå‚³é€æ‰€æœ‰å¿…需的物件" #: builtin/fetch.c #, c-format @@ -7162,8 +7344,8 @@ msgstr "é¸é …「%sã€çš„值「%sã€å° %s 無效" #: builtin/fetch.c #, c-format -msgid "option \"%s\" is ignored for %s\n" -msgstr "é¸é …「%sã€è¢« %s 忽略\n" +msgid "option \"%s\" is ignored for %s" +msgstr "é¸é …「%sã€è¢« %s 忽略" #: builtin/fetch.c object-file.c #, c-format @@ -7363,7 +7545,7 @@ msgstr "在所有更新分支上檢查強制更新" #: builtin/fetch.c msgid "write the commit-graph after fetching" -msgstr "抓å–後寫入分支圖" +msgstr "抓å–後寫入æäº¤åœ–" #: builtin/fetch.c msgid "accept refspecs from stdin" @@ -7539,6 +7721,10 @@ msgid "config key storing a list of repository paths" msgstr "儲å˜ç‰ˆæœ¬åº«è·¯å¾‘清單的è¨å®šéµ" #: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "命令在版本庫ä¸å¤±æ•—時ä»ç¹¼çºŒåŸ·è¡Œ" + +#: builtin/for-each-repo.c msgid "missing --config=<config>" msgstr "缺少 --config=<è¨å®š>" @@ -7753,12 +7939,12 @@ msgstr "%s:%s çš„ resolve-undo ä¸çš„ sha1 指標無效" #: builtin/fsck.c #, c-format msgid "unable to load rev-index for pack '%s'" -msgstr "ç„¡æ³•è®€å– â€œ%s†å°è£çš„修訂版索引 (rev-index)" +msgstr "無法讀å–「%sã€å°è£çš„修訂版索引 (rev-index)" #: builtin/fsck.c #, c-format msgid "invalid rev-index for pack '%s'" -msgstr "“%s†å°è£çš„修訂版索引 (rev-index) 無效" +msgstr "「%sã€å°è£çš„修訂版索引 (rev-index) 無效" #: builtin/fsck.c msgid "" @@ -8005,6 +8191,10 @@ msgid "enable auto-gc mode" msgstr "啟用自動垃圾回收模å¼" #: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "在背景執行垃圾回收" + +#: builtin/gc.c msgid "force running gc even if there may be another gc running" msgstr "強制執行 gc å³ä½¿å¦å¤–一個 gc æ£åœ¨åŸ·è¡Œ" @@ -8065,7 +8255,7 @@ msgstr "無法è˜åˆ¥çš„ --schedule 引數 '%s'" #: builtin/gc.c msgid "failed to write commit-graph" -msgstr "無法寫入æäº¤åœ–å½¢" +msgstr "無法寫入æäº¤åœ–" #: builtin/gc.c msgid "failed to prefetch remotes" @@ -8121,6 +8311,10 @@ msgid "run tasks based on the state of the repository" msgstr "基於版本庫狀態執行作æ¥" #: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "在背景執行ç¶è·" + +#: builtin/gc.c msgid "frequency" msgstr "frequency" @@ -8192,7 +8386,7 @@ msgstr "無法啟動 schtasks" #: builtin/gc.c msgid "failed to run 'crontab -l'; your system might not support 'cron'" -msgstr "無法執行 “crontab -lâ€ï¼›æ‚¨çš„系統å¯èƒ½ä¸æ”¯æ´ “cronâ€" +msgstr "無法執行「crontab -lã€ï¼›æ‚¨çš„系統å¯èƒ½ä¸æ”¯æ´ã€Œcronã€" #: builtin/gc.c msgid "failed to create crontab temporary file" @@ -8204,11 +8398,11 @@ msgstr "ç„¡æ³•é–‹å•Ÿæš«å˜æª”" #: builtin/gc.c msgid "failed to run 'crontab'; your system might not support 'cron'" -msgstr "無法執行 “crontabâ€ï¼›æ‚¨çš„系統å¯èƒ½ä¸æ”¯æ´ “cronâ€" +msgstr "無法執行「crontabã€ï¼›æ‚¨çš„系統å¯èƒ½ä¸æ”¯æ´ã€Œcronã€" #: builtin/gc.c msgid "'crontab' died" -msgstr "“crontabâ€ çµæŸé‹ä½œ" +msgstr "「crontabã€çµæŸé‹ä½œ" #: builtin/gc.c builtin/worktree.c #, c-format @@ -8284,7 +8478,6 @@ msgstr "grep:無法建立執行緒:%s" msgid "invalid number of threads specified (%d) for %s" msgstr "為 %2$s è¨å®šçš„執行緒數 (%1$d) 無效" -#. #-#-#-#-# grep.c.po #-#-#-#-# #. TRANSLATORS: %s is the configuration #. variable for tweaking threads, currently #. grep.threads @@ -9135,7 +9328,7 @@ msgstr "--only-trailers --only-input --unfold 的別å" #: builtin/interpret-trailers.c msgid "do not treat \"---\" as the end of input" -msgstr "ä¸è¦æŠŠ “---†當作輸入çµå°¾" +msgstr "ä¸è¦æŠŠã€Œ---ã€ç•¶ä½œè¼¸å…¥çµå°¾" #: builtin/interpret-trailers.c msgid "trailer(s) to add" @@ -9207,10 +9400,6 @@ msgid "Final output: %d %s\n" msgstr "最終輸出:%d %s\n" #: builtin/log.c -msgid "unable to create temporary object directory" -msgstr "無法建立暫å˜ç‰©ä»¶ç›®éŒ„" - -#: builtin/log.c #, c-format msgid "git show %s: bad file" msgstr "git show %s: æå£žçš„æª”案" @@ -9250,7 +9439,7 @@ msgstr "䏿˜¯ä¸€å€‹ç¯„åœ" #: builtin/log.c #, c-format msgid "unable to read branch description file '%s'" -msgstr "無法讀å–分支æè¿°æª” “%sâ€" +msgstr "無法讀å–分支æè¿°æª”「%sã€" #: builtin/log.c msgid "cover letter needs email format" @@ -9367,8 +9556,12 @@ msgid "max length of output filename" msgstr "輸出檔å的最大長度" #: builtin/log.c -msgid "use [RFC PATCH] instead of [PATCH]" -msgstr "使用 [RFC PATCH] 代替 [PATCH]" +msgid "rfc" +msgstr "rfc" + +#: builtin/log.c +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "在「PATCHã€å‰å† 上 <rfc>(é è¨ç‚ºã€ŒRFCã€ï¼‰" #: builtin/log.c msgid "cover-from-description-mode" @@ -9711,11 +9904,11 @@ msgstr "" #: builtin/ls-remote.c msgid "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" msgstr "" -"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" " [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" " [--symref] [<repository> [<patterns>...]]" @@ -9736,9 +9929,13 @@ msgid "limit to tags" msgstr "åƒ…é™æ–¼æ¨™ç±¤" #: builtin/ls-remote.c -msgid "limit to heads" +msgid "limit to branches" msgstr "åƒ…é™æ–¼åˆ†æ”¯" +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "--branches 已棄用的åŒç¾©è©ž" + #: builtin/ls-remote.c msgid "do not show peeled tags" msgstr "ä¸é¡¯ç¤ºå·²è§£æžçš„æ¨™ç±¤" @@ -9928,18 +10125,6 @@ msgstr "使用基於 diff3 çš„åˆä½µ" msgid "use a zealous diff3 based merge" msgstr "使用基於 zealous diff3 çš„åˆä½µ" -#: builtin/merge-file.c -msgid "for conflicts, use our version" -msgstr "如果è¡çªï¼Œä½¿ç”¨æˆ‘們的版本" - -#: builtin/merge-file.c -msgid "for conflicts, use their version" -msgstr "如果è¡çªï¼Œä½¿ç”¨ä»–們的版本" - -#: builtin/merge-file.c -msgid "for conflicts, use a union version" -msgstr "如果è¡çªï¼Œä½¿ç”¨è¯åˆç‰ˆæœ¬" - #: builtin/merge-file.c diff.c msgid "<algorithm>" msgstr "<演算法>" @@ -9963,7 +10148,7 @@ msgstr "為 檔案1/åˆå§‹æª”案/檔案2 è¨å®šæ¨™ç±¤" #: builtin/merge-file.c #, c-format msgid "object '%s' does not exist" -msgstr "物件 “%s†ä¸å˜åœ¨" +msgstr "物件「%sã€ä¸å˜åœ¨" #: builtin/merge-file.c msgid "Could not write object file" @@ -10235,7 +10420,7 @@ msgstr "ä¸èƒ½å¯«å…¥ç´¢å¼•。" msgid "Not handling anything other than two heads merge." msgstr "未處ç†å…©å€‹é åˆä½µä¹‹å¤–的任何動作。" -#: builtin/merge.c +#: builtin/merge.c builtin/sparse-checkout.c #, c-format msgid "unable to write %s" msgstr "ä¸èƒ½å¯« %s" @@ -10527,6 +10712,10 @@ msgid "write multi-pack bitmap" msgstr "寫入多包ä½åœ–" #: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "å¯«å…¥æ–°çš„å¢žé‡ MIDX" + +#: builtin/multi-pack-index.c msgid "write multi-pack index containing only given indexes" msgstr "寫入åªåŒ…嫿Œ‡å®šç´¢å¼•的多包索引" @@ -11215,7 +11404,7 @@ msgstr "ä¸ä¸€è‡´çš„差異計數" #: builtin/pack-objects.c #, c-format msgid "invalid pack.allowPackReuse value: '%s'" -msgstr "無效的 pack.allowPackReuse 值:“%sâ€" +msgstr "無效的 pack.allowPackReuse 值:「%sã€" #: builtin/pack-objects.c #, c-format @@ -11223,8 +11412,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 @@ -11860,7 +12049,7 @@ msgid "" "To choose either option permanently, see push.default in 'git help config'.\n" msgstr "" "\n" -"è‹¥è¦æ°¸ä¹…鏿“‡æŸå€‹é¸é …,請åƒé–± “git help config†ä¸çš„ push.default。\n" +"è‹¥è¦æ°¸ä¹…鏿“‡æŸå€‹é¸é …,請åƒé–±ã€Œgit help configã€ä¸çš„ push.default。\n" #: builtin/push.c msgid "" @@ -11871,8 +12060,8 @@ msgid "" msgstr "" "\n" "è‹¥è¦é¿å…在å稱與本機分支ä¸åŒæ™‚自動è¨å®šä¸Šæ¸¸åˆ†æ”¯ï¼Œ\n" -"è«‹åƒé–± “git help configâ€ ä¸ branch.autoSetupMerge çš„\n" -"“simple†é¸é …。\n" +"è«‹åƒé–±ã€Œgit help configã€ä¸ branch.autoSetupMerge çš„\n" +"「simpleã€é¸é …。\n" #: builtin/push.c #, c-format @@ -11919,8 +12108,8 @@ msgid "" "upstream, see 'push.autoSetupRemote' in 'git help config'.\n" msgstr "" "\n" -"è‹¥è¦ä½¿æ²’有追蹤上游的分支自動é…置,請åƒé–± “git help config†ä¸çš„\n" -"“push.autoSetupRemoteâ€ã€‚\n" +"è‹¥è¦ä½¿æ²’有追蹤上游的分支自動é…置,請åƒé–±ã€Œgit help configã€ä¸çš„\n" +"「push.autoSetupRemoteã€ã€‚\n" #: builtin/push.c #, c-format @@ -11965,8 +12154,8 @@ msgid "" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" "æ›´æ–°è¢«æ‹’çµ•ï¼Œå› ç‚ºæ‚¨ç›®å‰åˆ†æ”¯çš„æœ€æ–°æäº¤è½å¾Œæ–¼å…¶å°æ‡‰çš„é 端分支。\n" -"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ “git pullâ€ã€‚詳見\n" -"“git push --help†ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" +"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ã€Œgit pullã€ã€‚詳見\n" +"「git push --helpã€ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" #: builtin/push.c msgid "" @@ -11976,8 +12165,8 @@ msgid "" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" "æ›´æ–°è¢«æ‹’çµ•ï¼Œå› ç‚ºæŽ¨é€çš„æŸåˆ†æ”¯çš„æœ€æ–°æäº¤è½å¾Œæ–¼å…¶å°æ‡‰çš„é 端分支。\n" -"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ “git pullâ€ã€‚詳見\n" -"“git push --help†ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" +"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ã€Œgit pullã€ã€‚詳見\n" +"「git push --helpã€ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" #: builtin/push.c msgid "" @@ -11989,7 +12178,7 @@ msgid "" msgstr "" "æ›´æ–°è¢«æ‹’çµ•ï¼Œå› ç‚ºé ç«¯åŒ…å«æ‚¨æœ¬æ©Ÿæ²’有的æäº¤ã€‚é€™é€šå¸¸æ˜¯å› ç‚º\n" "å¦ä¸€å€‹ç‰ˆæœ¬åº«æœ‰æŽ¨é€æ›´å‹•到åŒå€‹å¼•ç”¨ã€‚å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé 端更動,\n" -"è«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ “git pullâ€ã€‚詳見 “git push --help†ä¸çš„\n" +"è«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ã€Œgit pullã€ã€‚詳見「git push --helpã€ä¸çš„\n" "〈Note about fast-forwards〉å°ç¯€ã€‚" #: builtin/push.c @@ -12013,8 +12202,8 @@ msgid "" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" "æ›´æ–°è¢«æ‹’çµ•ï¼Œå› ç‚ºé 端追蹤分支的最新æäº¤è‡ªä¸Šæ¬¡ç°½å‡ºå¾Œæœ‰æ”¹è®Šã€‚\n" -"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ “git pullâ€ã€‚\n" -"詳見 “git push --help†ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" +"å¦‚æžœæ‚¨æƒ³è¦æ•´åˆé ç«¯æ›´å‹•ï¼Œè«‹åœ¨å†æ¬¡æŽ¨é€å‰ä½¿ç”¨ã€Œgit pullã€ã€‚\n" +"詳見「git push --helpã€ä¸çš„〈Note about fast-forwards〉å°ç¯€ã€‚" #: builtin/push.c #, c-format @@ -12607,8 +12796,8 @@ msgid "" "which is no longer supported; use 'merges' instead" msgstr "" "--preserve-merges 已被 --rebase-merges å–代\n" -"註:您的 `pull.rebase` è¨å®šå¯èƒ½ä¹Ÿè¢«è¨å®šç‚ºä¸å—支æ´çš„ “preserveâ€ï¼›\n" -"請改用 “mergesâ€" +"註:您的 `pull.rebase` è¨å®šå¯èƒ½ä¹Ÿè¢«è¨å®šç‚ºä¸å—支æ´çš„「preserveã€ï¼›\n" +"請改用「mergesã€" #: builtin/rebase.c msgid "no rebase in progress" @@ -12928,6 +13117,39 @@ msgstr "未指定è¦åˆªé™¤çš„引用日誌" 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]" + +#: builtin/refs.c +msgid "git refs verify [--strict] [--verbose]" +msgstr "git refs verify [--strict] [--verbose]" + +#: builtin/refs.c +msgid "specify the reference format to convert to" +msgstr "指定è¦è½‰æ›æˆçš„å¼•ç”¨æ ¼å¼" + +#: builtin/refs.c +msgid "perform a non-destructive dry-run" +msgstr "進行éžç ´å£žæ€§çš„試執行" + +#: builtin/refs.c +msgid "missing --ref-format=<format>" +msgstr "缺少 --ref-format=<æ ¼å¼>" + +#: builtin/refs.c +#, c-format +msgid "repository already uses '%s' format" +msgstr "版本庫已經使用 '%s' æ ¼å¼" + +#: builtin/refs.c +msgid "enable strict checking" +msgstr "å•Ÿç”¨åš´æ ¼æª¢æŸ¥" + +#: builtin/refs.c +msgid "'git refs verify' takes no arguments" +msgstr "「git refs verifyã€ä¸æŽ¥å—引數" + #: builtin/remote.c msgid "" "git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" @@ -13273,10 +13495,6 @@ msgstr "* é 端 %s" msgid " Fetch URL: %s" msgstr " å–å¾—ä½å€ï¼š%s" -#: builtin/remote.c -msgid "(no URL)" -msgstr "(ç„¡ URL)" - #. TRANSLATORS: the colon ':' should align #. with the one in " Fetch URL: %s" #. translation. @@ -13287,6 +13505,10 @@ msgid " Push URL: %s" msgstr " 推é€ä½å€ï¼š%s" #: builtin/remote.c +msgid "(no URL)" +msgstr "(ç„¡ URL)" + +#: builtin/remote.c #, c-format msgid " HEAD branch: %s" msgstr " HEAD 分支:%s" @@ -13421,11 +13643,6 @@ msgid "return all URLs" msgstr "返回所有 URL ä½å€" #: builtin/remote.c -#, c-format -msgid "no URLs configured for remote '%s'" -msgstr "沒有給é 端版本庫 '%s' è¨å®š URL" - -#: builtin/remote.c msgid "manipulate push URLs" msgstr "å‹•ä½œæŽ¨é€ URLS" @@ -13632,7 +13849,7 @@ msgstr "ä¸èƒ½åˆªé™¤çå“版本庫ä¸çš„å°åŒ…" #: builtin/repack.c #, c-format msgid "option '%s' can only be used along with '%s'" -msgstr "“%s†é¸é …åªèƒ½èˆ‡ “%s†一起使用" +msgstr "「%sã€é¸é …åªèƒ½èˆ‡ã€Œ%sã€ä¸€èµ·ä½¿ç”¨" #: builtin/repack.c msgid "Nothing new to pack." @@ -13646,7 +13863,7 @@ msgstr "ç„¡æ³•å°‡åŒ…é‡æ–°å‘½å為「%sã€" #: builtin/repack.c #, c-format msgid "pack-objects did not write a '%s' file for pack %s-%s" -msgstr "pack-objects 沒有為 %2$s-%3$s 套件包寫入 “%1$s†檔案" +msgstr "pack-objects 沒有為 %2$s-%3$s 套件包寫入「%1$sã€æª”案" #: builtin/repack.c sequencer.c #, c-format @@ -13955,7 +14172,7 @@ msgstr "å¿…é ˆå‚³å…¥ --onto 或 --advance é¸é …" msgid "" "some rev walking options will be overridden as '%s' bit in 'struct rev_info' " "will be forced" -msgstr "å°‡è¦†å¯«éƒ¨åˆ†ä¿®è¨‚ç‰ˆéæ·é¸é …,強制使用 “struct rev_info†的 “%s†ä½å…ƒ" +msgstr "å°‡è¦†å¯«éƒ¨åˆ†ä¿®è¨‚ç‰ˆéæ·é¸é …,強制使用「struct rev_infoã€çš„「%sã€ä½å…ƒ" #: builtin/replay.c msgid "error preparing revisions" @@ -14345,7 +14562,7 @@ msgstr "已棄用:請改用 --empty=keep" #: builtin/revert.c msgid "use the 'reference' format to refer to commits" -msgstr "請使用 “referenceâ€ æ ¼å¼åƒè€ƒæäº¤" +msgstr "請使用「referenceã€æ ¼å¼åƒè€ƒæäº¤" #: builtin/revert.c msgid "revert failed" @@ -14669,12 +14886,12 @@ msgstr "未知的雜湊算法" #: builtin/show-ref.c msgid "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" msgstr "" "git show-ref [--head] [-d | --dereference]\n" -" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" -" [--heads] [--] [<pattern>...]" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" #: builtin/show-ref.c msgid "" @@ -14703,12 +14920,12 @@ msgid "failed to look up reference" msgstr "無法查詢引用" #: builtin/show-ref.c -msgid "only show tags (can be combined with heads)" -msgstr "åªé¡¯ç¤ºæ¨™ç±¤ï¼ˆå¯ä»¥å’Œé 共用)" +msgid "only show tags (can be combined with --branches)" +msgstr "åªé¡¯ç¤ºæ¨™ç±¤ï¼ˆå¯ä»¥å’Œ --branches 共用)" #: builtin/show-ref.c -msgid "only show heads (can be combined with tags)" -msgstr "åªé¡¯ç¤ºé (å¯ä»¥å’Œæ¨™ç±¤å…±ç”¨ï¼‰" +msgid "only show branches (can be combined with --tags)" +msgstr "åªé¡¯ç¤ºåˆ†æ”¯ï¼ˆå¯ä»¥å’Œ --tags 共用)" #: builtin/show-ref.c msgid "check for reference existence without resolving" @@ -14771,6 +14988,11 @@ msgid "failed to create directory for sparse-checkout file" msgstr "無法建立稀ç–簽出檔案的目錄" #: builtin/sparse-checkout.c +#, c-format +msgid "unable to fdopen %s" +msgstr "無法 fdopen %s" + +#: builtin/sparse-checkout.c msgid "failed to initialize worktree config" msgstr "無法åˆå§‹åŒ–工作å€çµ„æ…‹" @@ -15322,8 +15544,8 @@ msgstr "無法雜湊來自 '%s' 的物件" #: builtin/submodule--helper.c #, c-format -msgid "unexpected mode %o\n" -msgstr "éžé æœŸçš„æ¨¡å¼ %o\n" +msgid "unexpected mode %o" +msgstr "éžé æœŸçš„æ¨¡å¼ %o" #: builtin/submodule--helper.c msgid "use the commit stored in the index instead of the submodule HEAD" @@ -15440,7 +15662,7 @@ msgstr "" #: builtin/submodule--helper.c #, c-format msgid "could not get a repository handle for gitdir '%s'" -msgstr "無法å–å¾— gitdir “%s†的版本庫控點" +msgstr "無法å–å¾— gitdir「%sã€çš„版本庫控點" #: builtin/submodule--helper.c #, c-format @@ -15457,20 +15679,20 @@ msgstr "ä¸èƒ½è˜åˆ¥ submodule.alternateErrorStrategy çš„å–值 '%s'" msgid "Value '%s' for submodule.alternateLocation is not recognized" msgstr "ä¸èƒ½è˜åˆ¥ submodule.alternateLocation çš„å–值 '%s'" -#: builtin/submodule--helper.c +#: builtin/submodule--helper.c submodule.c #, c-format msgid "refusing to create/use '%s' in another submodule's git dir" msgstr "æ‹’çµ•åœ¨å…¶ä»–åæ¨¡çµ„çš„ git 路徑建立ï¼ä½¿ç”¨ã€Œ%sã€" #: builtin/submodule--helper.c #, c-format -msgid "clone of '%s' into submodule path '%s' failed" -msgstr "無法複製 '%s' åˆ°åæ¨¡çµ„路徑 '%s'" +msgid "directory not empty: '%s'" +msgstr "ç›®éŒ„ä¸æ˜¯ç©ºçš„:「%sã€" #: builtin/submodule--helper.c #, c-format -msgid "directory not empty: '%s'" -msgstr "ç›®éŒ„ä¸æ˜¯ç©ºçš„:「%sã€" +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "無法複製 '%s' åˆ°åæ¨¡çµ„路徑 '%s'" #: builtin/submodule--helper.c #, c-format @@ -15542,7 +15764,7 @@ msgstr "ç•¥éŽå模組 '%s'" #: builtin/submodule--helper.c #, c-format msgid "cannot clone submodule '%s' without a URL" -msgstr "無法在沒有網å€çš„æƒ…æ³ä¸‹è¤‡è£½ “%sâ€ åæ¨¡çµ„" +msgstr "無法在沒有網å€çš„æƒ…æ³ä¸‹è¤‡è£½ã€Œ%sã€å模組" #: builtin/submodule--helper.c #, c-format @@ -15660,15 +15882,15 @@ msgstr "ä¸å¾žé 端站å°å–得新物件" #: builtin/submodule--helper.c msgid "use the 'checkout' update strategy (default)" -msgstr "使用 “checkout†更新ç–略(é è¨å€¼ï¼‰" +msgstr "使用「checkoutã€æ›´æ–°ç–略(é è¨å€¼ï¼‰" #: builtin/submodule--helper.c msgid "use the 'merge' update strategy" -msgstr "使用 “merge†更新ç–ç•¥" +msgstr "使用「mergeã€æ›´æ–°ç–ç•¥" #: builtin/submodule--helper.c msgid "use the 'rebase' update strategy" -msgstr "使用 “rebase†更新ç–ç•¥" +msgstr "使用「rebaseã€æ›´æ–°ç–ç•¥" #: builtin/submodule--helper.c msgid "create a shallow clone truncated to the specified number of revisions" @@ -15911,9 +16133,11 @@ msgstr "æ›´æ–°çš„åŽŸå› " #: builtin/tag.c msgid "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" msgstr "" "git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" " <tagname> [<commit> | <object>]" #: builtin/tag.c @@ -16081,7 +16305,7 @@ msgstr "åªåˆ—å°æŒ‡å‘該物件的標籤" #: builtin/tag.c msgid "could not start 'git column'" -msgstr "無法啟動 “git columnâ€" +msgstr "無法啟動「git columnã€" #: builtin/tag.c #, c-format @@ -16511,7 +16735,7 @@ msgstr "git worktree unlock <worktree>" #: builtin/worktree.c msgid "No possible source branch, inferring '--orphan'" -msgstr "沒有å¯èƒ½çš„來æºåˆ†æ”¯ï¼ŒæŽ¨æ¸¬ç‚º “--orphanâ€" +msgstr "沒有å¯èƒ½çš„來æºåˆ†æ”¯ï¼ŒæŽ¨æ¸¬ç‚ºã€Œ--orphanã€" #: builtin/worktree.c #, c-format @@ -16646,8 +16870,8 @@ msgid "" "HEAD contents: '%s'" msgstr "" "HEAD 指å‘無效(或å¤ç«‹ï¼‰å¼•用。\n" -"HEAD 路徑:“%sâ€\n" -"HEAD 內容:“%sâ€" +"HEAD 路徑:「%sã€\n" +"HEAD 內容:「%sã€" #: builtin/worktree.c msgid "" @@ -16655,7 +16879,7 @@ msgid "" "present, stopping; use 'add -f' to override or fetch a remote first" msgstr "" "å³ä½¿æœ‰æä¾›ä¸€å€‹é 端,å»ä¸å˜åœ¨æœ¬æ©Ÿæˆ–é 端引用,\n" -"æ•…åœæ¢ã€‚使用 “add -f†先覆蓋或抓å–é 端" +"æ•…åœæ¢ã€‚使用「add -fã€å…ˆè¦†è“‹æˆ–抓å–é 端" #: builtin/worktree.c msgid "checkout <branch> even if already checked out in other worktree" @@ -16866,12 +17090,12 @@ msgstr "core.fsyncMethod = batch 䏿”¯æ´æœ¬å¹³å°" #: bundle-uri.c #, c-format msgid "could not parse bundle list key %s with value '%s'" -msgstr "無法解æžå¥—ä»¶åŒ…æ¸…å–®éµ %s 的值 “%sâ€" +msgstr "無法解æžå¥—ä»¶åŒ…æ¸…å–®éµ %s 的值「%sã€" #: bundle-uri.c #, c-format msgid "bundle list at '%s' has no mode" -msgstr "使–¼ “%s†的套件包清單沒有模å¼" +msgstr "使–¼ã€Œ%sã€çš„套件包清單沒有模å¼" #: bundle-uri.c msgid "failed to create temporary file" @@ -16884,7 +17108,7 @@ msgstr "功能ä¸è¶³" #: bundle-uri.c #, c-format msgid "file downloaded from '%s' is not a bundle" -msgstr "從 “%sâ€ ä¸‹è¼‰çš„æª”æ¡ˆä¸æ˜¯å¥—件包" +msgstr "從「%sã€ä¸‹è¼‰çš„æª”æ¡ˆä¸æ˜¯å¥—件包" #: bundle-uri.c msgid "failed to store maximum creation token" @@ -16893,7 +17117,7 @@ msgstr "ç„¡æ³•å„²å˜æœ€å¤§çš„建立權æ–" #: bundle-uri.c #, c-format msgid "unrecognized bundle mode from URI '%s'" -msgstr "無法è˜åˆ¥å¾ž URI “%s†å–回的套件包模å¼" +msgstr "無法è˜åˆ¥å¾ž URI「%sã€å–回的套件包模å¼" #: bundle-uri.c #, c-format @@ -16903,17 +17127,17 @@ msgstr "超出套件包 URI éžè¿´é™åˆ¶ (%d)" #: bundle-uri.c #, c-format msgid "failed to download bundle from URI '%s'" -msgstr "無法從 “%s†URI 下載套件包" +msgstr "無法從「%sã€URI 下載套件包" #: bundle-uri.c #, c-format msgid "file at URI '%s' is not a bundle or bundle list" -msgstr "使–¼ URI “%sâ€ çš„æª”æ¡ˆä¸æ˜¯å¥—件包或套件包清單" +msgstr "使–¼ URI「%sã€çš„æª”æ¡ˆä¸æ˜¯å¥—件包或套件包清單" #: bundle-uri.c #, c-format msgid "bundle-uri: unexpected argument: '%s'" -msgstr "bundle-uri: éžé 期的引數:“%sâ€" +msgstr "bundle-uri: éžé 期的引數:「%sã€" #: bundle-uri.c msgid "bundle-uri: expected flush after arguments" @@ -16925,7 +17149,7 @@ msgstr "bundle-uri: 收到空白列" #: bundle-uri.c msgid "bundle-uri: line is not of the form 'key=value'" -msgstr "bundle-uri: åˆ—çš„æ ¼å¼ä¸æ˜¯ “key=valueâ€" +msgstr "bundle-uri: åˆ—çš„æ ¼å¼ä¸æ˜¯ã€Œkey=valueã€" #: bundle-uri.c msgid "bundle-uri: line has empty key or value" @@ -16944,7 +17168,7 @@ msgstr "未知功能「%sã€" #: bundle.c #, c-format msgid "'%s' does not look like a v2 or v3 bundle file" -msgstr "“%s†ä¸åƒæ˜¯ä¸€å€‹ v2 或 v3 版本的套件包檔案" +msgstr "「%sã€ä¸åƒæ˜¯ä¸€å€‹ v2 或 v3 版本的套件包檔案" #: bundle.c #, c-format @@ -16956,10 +17180,6 @@ msgid "Repository lacks these prerequisite commits:" msgstr "版本庫ä¸ç¼ºå°‘這些必備的æäº¤ï¼š" #: bundle.c -msgid "need a repository to verify a bundle" -msgstr "需è¦ç‰ˆæœ¬åº«é©—è‰å¥—件包" - -#: bundle.c msgid "" "some prerequisite commits exist in the object store, but are not connected " "to the repository's history" @@ -17478,6 +17698,10 @@ msgid "Manage reflog information" msgstr "ç®¡ç† reflog 訊æ¯" #: command-list.h +msgid "Low-level access to refs" +msgstr "å°å¼•用的低階å˜å–" + +#: command-list.h msgid "Manage set of tracked repositories" msgstr "管ç†å·²è¿½è¹¤ç‰ˆæœ¬åº«" @@ -17572,7 +17796,7 @@ msgstr "將工作å€é™ç¸®è‡³åªåŒ…å«è¿½è¹¤æª”案的å集" #: command-list.h msgid "Add file contents to the staging area" -msgstr "將檔案內容新增到索引" +msgstr "將檔案內容新增到暫å˜å€" #: command-list.h msgid "Stash the changes in a dirty working directory away" @@ -17720,7 +17944,7 @@ msgstr "Git å°åŒ…æ ¼å¼" #: command-list.h msgid "Git cryptographic signature formats" -msgstr "Git 密碼編è¯ç°½ç« æ ¼å¼" +msgstr "Git 數ä½ç°½ç« æ ¼å¼" #: command-list.h msgid "A Git Glossary" @@ -17808,104 +18032,111 @@ msgstr "用來管ç†å¤§åž‹ Git 版本庫的工具" #: commit-graph.c msgid "commit-graph file is too small" -msgstr "æäº¤åœ–形檔案太å°" +msgstr "æäº¤åœ–檔案太å°" #: commit-graph.c msgid "commit-graph oid fanout chunk is wrong size" -msgstr "æäº¤åœ–å½¢ OID 扇出å€å¡Šå¤§å°æœ‰èª¤" +msgstr "æäº¤åœ– OID 扇出å€å¡Šå¤§å°æœ‰èª¤" #: commit-graph.c msgid "commit-graph fanout values out of order" -msgstr "æäº¤åœ–形扇出的數值失åº" +msgstr "æäº¤åœ–扇出的數值失åº" #: commit-graph.c msgid "commit-graph OID lookup chunk is the wrong size" -msgstr "æäº¤åœ–å½¢ OID 查詢å€å¡Šçš„大尿œ‰èª¤" +msgstr "æäº¤åœ– OID 查詢å€å¡Šçš„大尿œ‰èª¤" #: commit-graph.c msgid "commit-graph commit data chunk is wrong size" -msgstr "æäº¤åœ–形的æäº¤è³‡æ–™å€å¡Šå¤§å°æœ‰èª¤" +msgstr "æäº¤åœ–çš„æäº¤è³‡æ–™å€å¡Šå¤§å°æœ‰èª¤" #: commit-graph.c msgid "commit-graph generations chunk is wrong size" -msgstr "æäº¤åœ–形的世代å€å¡Šå¤§å°æœ‰èª¤" +msgstr "æäº¤åœ–的世代å€å¡Šå¤§å°æœ‰èª¤" #: commit-graph.c msgid "commit-graph changed-path index chunk is too small" -msgstr "æäº¤åœ–形的更動路徑索引å€å¡ŠéŽå°" +msgstr "æäº¤åœ–的更動路徑索引å€å¡ŠéŽå°" #: commit-graph.c #, c-format msgid "" "ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-" "graph file" -msgstr "忽略æäº¤åœ–形檔案ä¸éŽå°çš„æ›´å‹•路徑å€å¡Š (%<PRIuMAX> < %<PRIuMAX>)" +msgstr "忽略æäº¤åœ–檔案ä¸éŽå°çš„æ›´å‹•路徑å€å¡Šï¼ˆ%<PRIuMAX> < %<PRIuMAX>)" #: commit-graph.c #, c-format msgid "commit-graph signature %X does not match signature %X" -msgstr "æäº¤åœ–形簽å %X 和簽å %X ä¸ç¬¦åˆ" +msgstr "æäº¤åœ–ç°½ç« %X å’Œç°½ç« %X ä¸ç¬¦" #: commit-graph.c #, c-format msgid "commit-graph version %X does not match version %X" -msgstr "æäº¤åœ–形版本 %X 和版本 %X ä¸ç¬¦åˆ" +msgstr "æäº¤åœ–版本 %X 和版本 %X ä¸ç¬¦" #: commit-graph.c #, c-format msgid "commit-graph hash version %X does not match version %X" -msgstr "æäº¤åœ–形雜湊版本 %X 和版本 %X ä¸ç¬¦åˆ" +msgstr "æäº¤åœ–雜湊版本 %X 和版本 %X ä¸ç¬¦" #: commit-graph.c #, c-format msgid "commit-graph file is too small to hold %u chunks" -msgstr "æäº¤åœ–形檔案ä¸å¤ 放置 %u 個å€å¡Š" +msgstr "æäº¤åœ–檔案ä¸å¤ 放置 %u 個å€å¡Š" #: commit-graph.c msgid "commit-graph required OID fanout chunk missing or corrupted" -msgstr "æäº¤åœ–形需è¦çš„ OID 扇出å€å¡Šéºå¤±æˆ–æå£ž" +msgstr "æäº¤åœ–需è¦çš„ OID 扇出å€å¡Šéºå¤±æˆ–æå£ž" #: commit-graph.c msgid "commit-graph required OID lookup chunk missing or corrupted" -msgstr "æäº¤åœ–形需è¦çš„ OID 查詢å€å¡Šéºå¤±æˆ–æå£ž" +msgstr "æäº¤åœ–需è¦çš„ OID 查詢å€å¡Šéºå¤±æˆ–æå£ž" #: commit-graph.c msgid "commit-graph required commit data chunk missing or corrupted" -msgstr "æäº¤åœ–形需è¦çš„æäº¤è³‡æ–™å€å¡Šéºå¤±æˆ–æå£ž" +msgstr "æäº¤åœ–需è¦çš„æäº¤è³‡æ–™å€å¡Šéºå¤±æˆ–æå£ž" + +#: commit-graph.c +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "由於ä¸ç›¸å®¹çš„è¨å®šï¼Œåœç”¨æäº¤åœ–層 '%s' çš„å¸ƒéš†éŽæ¿¾å™¨" #: commit-graph.c msgid "commit-graph has no base graphs chunk" -msgstr "æäº¤åœ–形沒有基礎圖形å€å¡Š" +msgstr "æäº¤åœ–沒有基礎圖å€å¡Š" #: commit-graph.c msgid "commit-graph base graphs chunk is too small" -msgstr "æäº¤åœ–形的基礎圖形å€å¡ŠéŽå°" +msgstr "æäº¤åœ–的基礎圖å€å¡ŠéŽå°" #: commit-graph.c msgid "commit-graph chain does not match" -msgstr "æäº¤åœ–å½¢éˆä¸ç¬¦åˆ" +msgstr "æäº¤åœ–éˆä¸ç¬¦" #: commit-graph.c #, c-format msgid "commit count in base graph too high: %<PRIuMAX>" -msgstr "基礎圖 (base graph) ä¸çš„æäº¤æ•¸éŽå¤šï¼š%<PRIuMAX>" +msgstr "基礎圖ä¸çš„æäº¤æ•¸éŽå¤šï¼š%<PRIuMAX>" #: commit-graph.c msgid "commit-graph chain file too small" -msgstr "æäº¤åœ–å½¢éˆæª”案éŽå°" +msgstr "æäº¤åœ–éˆæª”案éŽå°" #: commit-graph.c #, c-format msgid "invalid commit-graph chain: line '%s' not a hash" -msgstr "無效的æäº¤åœ–å½¢éˆï¼šã€Œ%sã€åˆ—䏿˜¯é›œæ¹Šå€¼" +msgstr "無效的æäº¤åœ–éˆï¼šã€Œ%sã€åˆ—䏿˜¯é›œæ¹Šå€¼" #: commit-graph.c msgid "unable to find all commit-graph files" -msgstr "無法找到所有æäº¤åœ–形檔案" +msgstr "無法找到所有æäº¤åœ–檔案" #: commit-graph.c msgid "invalid commit position. commit-graph is likely corrupt" -msgstr "無效的æäº¤ä½ç½®ã€‚æäº¤åœ–å½¢å¯èƒ½å·²æå£ž" +msgstr "無效的æäº¤ä½ç½®ã€‚æäº¤åœ–å¯èƒ½å·²æå£ž" #: commit-graph.c #, c-format @@ -17914,15 +18145,15 @@ msgstr "無法找到æäº¤ %s" #: commit-graph.c msgid "commit-graph requires overflow generation data but has none" -msgstr "æäº¤åœ–éœ€è¦æ¯”ç›®å‰æ›´å¤šçš„世代資料,但沒有相關資料" +msgstr "缺少æäº¤åœ–需è¦çš„æº¢ä½ä¸–代資料" #: commit-graph.c msgid "commit-graph overflow generation data is too small" -msgstr "æäº¤åœ–形的溢出世代資料éŽå°" +msgstr "æäº¤åœ–的溢ä½ä¸–代資料éŽå°" #: commit-graph.c msgid "commit-graph extra-edges pointer out of bounds" -msgstr "æäº¤åœ–形的延伸邊界指é‡è¶…出範åœ" +msgstr "æäº¤åœ–é¡å¤–的邊指標超出範åœ" #: commit-graph.c msgid "Loading known commits in commit graph" @@ -17930,7 +18161,7 @@ msgstr "æ£åœ¨è¼‰å…¥æäº¤åœ–ä¸çš„已知æäº¤" #: commit-graph.c msgid "Expanding reachable commits in commit graph" -msgstr "æ£åœ¨å±•é–‹æäº¤åœ–ä¸çš„å¯ä»¥å–å¾—çš„æäº¤" +msgstr "æ£åœ¨å±•é–‹æäº¤åœ–ä¸çš„å¯è§¸åŠæäº¤" #: commit-graph.c msgid "Clearing commit marks in commit graph" @@ -17938,11 +18169,11 @@ msgstr "æ£åœ¨æ¸…除æäº¤åœ–ä¸çš„æäº¤æ¨™è¨˜" #: commit-graph.c msgid "Computing commit graph topological levels" -msgstr "æ£åœ¨è¨ˆç®—æäº¤åœ–拓樸級別" +msgstr "æ£åœ¨è¨ˆç®—æäº¤åœ–的拓樸層級" #: commit-graph.c msgid "Computing commit graph generation numbers" -msgstr "æ£åœ¨è¨ˆç®—æäº¤åœ–世代數å—" +msgstr "æ£åœ¨è¨ˆç®—æäº¤åœ–的世代數" #: commit-graph.c msgid "Computing commit changed paths Bloom filters" @@ -17970,7 +18201,7 @@ msgstr "為 %s 開啟索引發生錯誤" #: commit-graph.c msgid "Finding commits for commit graph among packed objects" -msgstr "æ£åœ¨æ‰“包物件ä¸å°‹æ‰¾æäº¤åœ–çš„æäº¤" +msgstr "æ£åœ¨å¾žæ‰“包物件ä¸å°‹æ‰¾æäº¤åœ–çš„æäº¤" #: commit-graph.c msgid "Finding extra edges in commit graph" @@ -17978,13 +18209,13 @@ msgstr "æ£åœ¨å°‹æ‰¾æäº¤åœ–ä¸é¡å¤–的邊" #: commit-graph.c msgid "failed to write correct number of base graph ids" -msgstr "無法寫入æ£ç¢ºæ•¸é‡çš„基礎圖形 ID" +msgstr "無法寫入æ£ç¢ºæ•¸é‡çš„基礎圖 ID" #: commit-graph.c msgid "unable to create temporary graph layer" -msgstr "無法建立暫時的圖形層" +msgstr "無法建立暫時性圖層" -#: commit-graph.c +#: commit-graph.c midx-write.c #, c-format msgid "unable to adjust shared permissions for '%s'" msgstr "無法調整「%sã€çš„共用權é™" @@ -17997,25 +18228,25 @@ msgstr[0] "æ£åœ¨ç”¨ %d æ¥å¯«å‡ºæäº¤åœ–" #: commit-graph.c msgid "unable to open commit-graph chain file" -msgstr "無法開啟æäº¤åœ–å½¢éˆæª”案" +msgstr "無法開啟æäº¤åœ–éˆæª”案" #: commit-graph.c msgid "failed to rename base commit-graph file" -msgstr "ç„¡æ³•é‡æ–°å‘½å基礎æäº¤åœ–形檔案" +msgstr "ç„¡æ³•é‡æ–°å‘½å基礎æäº¤åœ–檔案" #: commit-graph.c msgid "failed to rename temporary commit-graph file" -msgstr "ç„¡æ³•é‡æ–°å‘½å暫時æäº¤åœ–形檔案" +msgstr "ç„¡æ³•é‡æ–°å‘½å暫時性æäº¤åœ–檔案" #: commit-graph.c #, c-format msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" -msgstr "無法將圖與 %<PRIuMAX>, %<PRIuMAX> 個æäº¤é€²è¡Œåˆä½µ" +msgstr "無法åˆä½µåœ–,兩者分別有 %<PRIuMAX>ã€%<PRIuMAX> 個æäº¤" #: commit-graph.c #, c-format msgid "cannot merge graph %s, too many commits: %<PRIuMAX>" -msgstr "無法åˆä½µ %s 圖,太多æäº¤ï¼š%<PRIuMAX>" +msgstr "無法åˆä½µåœ– %s,太多æäº¤ï¼š%<PRIuMAX>" #: commit-graph.c msgid "Scanning merged commits" @@ -18023,15 +18254,22 @@ msgstr "æ£åœ¨æŽƒæåˆä½µæäº¤" #: commit-graph.c msgid "Merging commit-graph" -msgstr "æ£åœ¨åˆä½µæäº¤åœ–å½¢" +msgstr "æ£åœ¨åˆä½µæäº¤åœ–" #: commit-graph.c msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" -msgstr "嘗試寫入æäº¤åœ–形,但 “core.commitGraph†已被åœç”¨" +msgstr "嘗試寫入æäº¤åœ–,但「core.commitGraphã€å·²åœç”¨" + +#: commit-graph.c +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph." +"changedPathsVersion' (%d) is not supported" +msgstr "嘗試寫入æäº¤åœ–ï¼Œä½†ä¸æ”¯æ´ã€ŒcommitGraph.changedPathsVersionã€ï¼ˆ%d)" #: commit-graph.c msgid "too many commits to write graph" -msgstr "æäº¤å¤ªå¤šä¸èƒ½ç•«åœ–" +msgstr "æäº¤éŽå¤šç„¡æ³•畫圖" #: commit-graph.c msgid "the commit-graph file has incorrect checksum and is likely corrupt" @@ -18040,59 +18278,59 @@ msgstr "æäº¤åœ–檔案的總和檢查碼錯誤,å¯èƒ½å·²ç¶“æå£ž" #: commit-graph.c #, c-format msgid "commit-graph has incorrect OID order: %s then %s" -msgstr "æäº¤åœ–形的物件 ID é †åºä¸æ£ç¢ºï¼š%s 然後 %s" +msgstr "æäº¤åœ–的物件 ID é †åºä¸æ£ç¢ºï¼š%s 然後 %s" #: commit-graph.c #, c-format msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u" -msgstr "æäº¤åœ–å½¢æœ‰ä¸æ£ç¢ºçš„æ‰‡å‡ºå€¼ï¼šfanout[%d] = %u != %u" +msgstr "æäº¤åœ–æœ‰ä¸æ£ç¢ºçš„æ‰‡å‡ºå€¼ï¼šfanout[%d] = %u != %u" #: commit-graph.c #, c-format msgid "failed to parse commit %s from commit-graph" -msgstr "無法從æäº¤åœ–å½¢ä¸è§£æžæäº¤ %s" +msgstr "無法從æäº¤åœ–ä¸è§£æžæäº¤ %s" #: commit-graph.c #, c-format msgid "failed to parse commit %s from object database for commit-graph" -msgstr "無法從æäº¤åœ–形的物件庫ä¸è§£æžæäº¤ %s" +msgstr "無法從æäº¤åœ–的物件資料庫ä¸è§£æžæäº¤ %s" #: commit-graph.c #, c-format msgid "root tree OID for commit %s in commit-graph is %s != %s" -msgstr "æäº¤åœ–å½¢ä¸çš„æäº¤ %s çš„æ ¹æ¨¹ç‹€ç‰©ä»¶ ID 是 %s != %s" +msgstr "æäº¤åœ–ä¸çš„æäº¤ %s çš„æ ¹æ¨¹ç‹€ç‰©ä»¶ ID 是 %s != %s" #: commit-graph.c #, c-format msgid "commit-graph parent list for commit %s is too long" -msgstr "æäº¤ %s çš„æäº¤åœ–形父æäº¤åˆ—表太長了" +msgstr "æäº¤ %s çš„æäº¤åœ–上級清單éŽé•·" #: commit-graph.c #, c-format msgid "commit-graph parent for %s is %s != %s" -msgstr "%s çš„æäº¤åœ–形父æäº¤æ˜¯ %s != %s" +msgstr "%s çš„æäº¤åœ–上級是 %s != %s" #: commit-graph.c #, c-format msgid "commit-graph parent list for commit %s terminates early" -msgstr "æäº¤ %s çš„æäº¤åœ–形父æäº¤åˆ—è¡¨éŽæ—©çµ‚æ¢" +msgstr "æäº¤ %s çš„æäº¤åœ–ä¸Šç´šæ¸…å–®éŽæ—©çµ‚æ¢" #: commit-graph.c #, c-format msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>" -msgstr "æäº¤ %s çš„æäº¤åœ–形處於 %<PRIuMAX> < %<PRIuMAX> 世代" +msgstr "æäº¤ %s 使–¼ %<PRIuMAX> < %<PRIuMAX> æäº¤åœ–世代" #: commit-graph.c #, c-format msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>" -msgstr "æäº¤åœ–å½¢ä¸æäº¤ %s çš„æäº¤æ—¥æœŸæ˜¯ %<PRIuMAX> != %<PRIuMAX>" +msgstr "æäº¤åœ–ä¸çš„æäº¤ %s æäº¤æ—¥æœŸæ˜¯ %<PRIuMAX> != %<PRIuMAX>" #: commit-graph.c #, c-format msgid "" "commit-graph has both zero and non-zero generations (e.g., commits '%s' and " "'%s')" -msgstr "æäº¤åœ–å½¢ä¸åŒ…å« 0 å’Œéž 0 兩個世代號(例如 “%s†和 “%s†æäº¤ï¼‰" +msgstr "æäº¤åœ–ä¸åŒ…å« 0 å’Œéž 0 兩個世代數(例如æäº¤ã€Œ%sã€å’Œã€Œ%sã€ï¼‰" #: commit-graph.c msgid "Verifying commits in commit graph" @@ -18131,7 +18369,7 @@ msgstr "" #: commit.c #, c-format msgid "commit %s exists in commit-graph but not in the object database" -msgstr "%s æäº¤åœ¨æäº¤åœ–å½¢ä¸ï¼Œä½†ä¸åœ¨ç‰©ä»¶è³‡æ–™åº«ä¸" +msgstr "%s æäº¤åœ¨æäº¤åœ–ä¸ï¼Œä½†ä¸åœ¨ç‰©ä»¶è³‡æ–™åº«ä¸" #: commit.c #, c-format @@ -18174,37 +18412,37 @@ msgstr "沒有å¯ç”¨çš„ libc 資訊\n" #: compat/disk.h #, c-format msgid "could not determine free disk size for '%s'" -msgstr "無法判斷 “%s†的剩餘ç£ç¢Ÿå¤§å°" +msgstr "無法判斷「%sã€çš„剩餘ç£ç¢Ÿå¤§å°" #: compat/disk.h #, c-format msgid "could not get info for '%s'" -msgstr "無法å–å¾— “%s†的資訊" +msgstr "無法å–得「%sã€çš„資訊" #: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "[GLE %ld] health thread could not open '%ls'" -msgstr "[GLE %ld] å¥åº·ç›£è½åŸ·è¡Œç·’無法開啟 “%lsâ€" +msgstr "[GLE %ld] å¥åº·ç›£è½åŸ·è¡Œç·’無法開啟「%lsã€" #: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "[GLE %ld] health thread getting BHFI for '%ls'" -msgstr "[GLE %ld] å¥åº·ç›£è½åŸ·è¡Œç·’å–å¾— “%ls†的 BHFI" +msgstr "[GLE %ld] å¥åº·ç›£è½åŸ·è¡Œç·’å–得「%lsã€çš„ BHFI" #: compat/fsmonitor/fsm-health-win32.c compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "could not convert to wide characters: '%s'" -msgstr "無法轉æ›è‡³è¼ƒå¯¬å—元:“%sâ€" +msgstr "無法轉æ›è‡³è¼ƒå¯¬å—元:「%sã€" #: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "BHFI changed '%ls'" -msgstr "BHFI 更改了 “%lsâ€" +msgstr "BHFI 更改了「%lsã€" #: compat/fsmonitor/fsm-health-win32.c #, c-format msgid "unhandled case in 'has_worktree_moved': %d" -msgstr "“has_worktree_movedâ€ ä¸æœ‰æœªè™•置的情æ³ï¼š%d" +msgstr "「has_worktree_movedã€ä¸æœ‰æœªè™•置的情æ³ï¼š%d" #: compat/fsmonitor/fsm-health-win32.c #, c-format @@ -18232,22 +18470,22 @@ msgstr "[GLE %ld] 無法將路徑轉æ›ç‚º UTF-8:「%.*lsã€" #: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "[GLE %ld] could not watch '%s'" -msgstr "[GLE %ld] ç„¡æ³•ç›£è½ â€œ%sâ€" +msgstr "[GLE %ld] 無法監è½ã€Œ%sã€" #: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "[GLE %ld] could not get longname of '%s'" -msgstr "[GLE %ld] 無法å–å¾— “%s†的 longname" +msgstr "[GLE %ld] 無法å–得「%sã€çš„ longname" #: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "ReadDirectoryChangedW failed on '%s' [GLE %ld]" -msgstr "在 “%sâ€ ä¸Šå‘¼å« ReadDirectoryChangedW 失敗 [GLE %ld]" +msgstr "在「%sã€ä¸Šå‘¼å« ReadDirectoryChangedW 失敗 [GLE %ld]" #: compat/fsmonitor/fsm-listen-win32.c #, c-format msgid "GetOverlappedResult failed on '%s' [GLE %ld]" -msgstr "在 “%sâ€ ä¸Šå‘¼å« GetOverlappedResult 失敗 [GLE %ld]" +msgstr "在「%sã€ä¸Šå‘¼å« GetOverlappedResult 失敗 [GLE %ld]" #: compat/fsmonitor/fsm-listen-win32.c #, c-format @@ -18292,7 +18530,7 @@ msgstr "無法複製 SID (%ld)" #: compat/mingw.c #, c-format msgid "failed to get owner for '%s' (%ld)" -msgstr "無法å–å¾— “%s†的所有者 (%ld)" +msgstr "無法å–得「%sã€çš„æ‰€æœ‰è€… (%ld)" #: compat/obstack.c msgid "memory exhausted" @@ -18381,7 +18619,7 @@ msgstr "ç„¡æ³•è®€å– IPC 回應" #: compat/simple-ipc/ipc-unix-socket.c #, c-format msgid "could not start accept_thread '%s'" -msgstr "無法啟動 accept_thread “%sâ€" +msgstr "無法啟動 accept_thread「%sã€" #: compat/simple-ipc/ipc-unix-socket.c #, c-format @@ -18391,26 +18629,26 @@ msgstr "無法啟動「%sã€çš„ worker[0]" #: compat/simple-ipc/ipc-win32.c #, c-format msgid "ConnectNamedPipe failed for '%s' (%lu)" -msgstr "å° â€œ%s†進行 ConnectNamedPipe 失敗 (%lu)" +msgstr "å°ã€Œ%sã€é€²è¡Œ ConnectNamedPipe 失敗 (%lu)" #: compat/simple-ipc/ipc-win32.c #, c-format msgid "could not create fd from pipe for '%s'" -msgstr "無法為 “%s†從管é“建立 fd" +msgstr "無法為「%sã€å¾žç®¡é“建立 fd" #: compat/simple-ipc/ipc-win32.c #, c-format msgid "could not start thread[0] for '%s'" -msgstr "無法為 “%s†啟動 thread[0]" +msgstr "無法為「%sã€å•Ÿå‹• thread[0]" #: compat/simple-ipc/ipc-win32.c #, c-format msgid "wait for hEvent failed for '%s'" -msgstr "ç‰å¾… “%s†的 hEvent 失敗" +msgstr "ç‰å¾…「%sã€çš„ hEvent 失敗" #: compat/terminal.c msgid "cannot resume in the background, please use 'fg' to resume" -msgstr "無法在背景繼續;請使用 “fg†繼續" +msgstr "無法在背景繼續;請使用「fgã€ç¹¼çºŒ" #: compat/terminal.c msgid "cannot restore terminal settings" @@ -18602,7 +18840,7 @@ msgstr "%s 變數的值無效" #: config.c #, c-format msgid "ignoring unknown core.fsync component '%s'" -msgstr "忽略未知的 core.fsync 組件「%sã€" +msgstr "忽略未知的 core.fsync 元件「%sã€" #: config.c #, c-format @@ -18778,7 +19016,7 @@ msgstr "無效的å°ç¯€å稱:%s" #: config.c #, c-format msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>" -msgstr "å› ç‚ºç¬¬ %2$<PRIuMAX> åˆ—ä¸ â€œ%1$s†的文å—列太長,故拒絕é‹ä½œ" +msgstr "å› ç‚ºç¬¬ %2$<PRIuMAX> 列ä¸ã€Œ%1$sã€çš„æ–‡å—列太長,故拒絕é‹ä½œ" #: config.c #, c-format @@ -18992,7 +19230,7 @@ msgstr "%s ä¸çš„ CRLF 將被 LF å–代" msgid "" "in the working copy of '%s', CRLF will be replaced by LF the next time Git " "touches it" -msgstr "在 “%s†的工作複本ä¸ï¼Œä¸‹æ¬¡ Git 接觸到時會用 LF å–代 CRLF" +msgstr "在「%sã€çš„工作複本ä¸ï¼Œä¸‹æ¬¡ Git 接觸到時會用 LF å–代 CRLF" #: convert.c #, c-format @@ -19004,7 +19242,7 @@ msgstr "檔案 %s ä¸çš„ LF 將被 CRLF å–代" msgid "" "in the working copy of '%s', LF will be replaced by CRLF the next time Git " "touches it" -msgstr "在 “%s†的工作複本ä¸ï¼Œä¸‹æ¬¡ Git 接觸到時會用 CRLF å–代 LF" +msgstr "在「%sã€çš„工作複本ä¸ï¼Œä¸‹æ¬¡ Git 接觸到時會用 CRLF å–代 LF" #: convert.c #, c-format @@ -19225,7 +19463,7 @@ msgstr "ä¸èƒ½é–‹å•Ÿç›®éŒ„ '%s'" #: diagnose.c #, c-format msgid "skipping '%s', which is neither file nor directory" -msgstr "ç•¥éŽ â€œ%sâ€ï¼Œå…¶éžæª”案或目錄" +msgstr "ç•¥éŽã€Œ%sã€ï¼Œå…¶éžæª”案或目錄" #: diagnose.c msgid "could not duplicate stdout" @@ -19314,7 +19552,7 @@ msgstr "color-moved-ws:allow-indentation-change ä¸èƒ½èˆ‡å…¶å®ƒç©ºç™½å—元模 msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "è¨å®šè®Šæ•¸ 'diff.submodule' 未知的å–值:'%s'" -#: diff.c transport.c +#: diff.c merge-recursive.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "è¨å®š '%s' çš„å–值未知:%s" @@ -19523,7 +19761,7 @@ msgstr "使用æä¾›çš„æª”案å長度生æˆå·®ç•°çµ±è¨ˆ" #: diff.c msgid "generate diffstat with a given graph width" -msgstr "使用æä¾›çš„圖形長度生æˆå·®ç•°çµ±è¨ˆ" +msgstr "產出é™åˆ¶ç‚ºæä¾›çš„寬度的差異統計圖形" #: diff.c msgid "<count>" @@ -20159,7 +20397,7 @@ msgstr "é æœŸ '%s',得到 '%s'" #: fetch-pack.c #, c-format msgid "expected '%s'" -msgstr "é æœŸ “%sâ€" +msgstr "é æœŸã€Œ%sã€" #: fetch-pack.c #, c-format @@ -20251,45 +20489,49 @@ msgstr "無法將「%sã€å‘½ä»¤å‚³é€åˆ° fsmonitor--daemon" #: fsmonitor-settings.c #, c-format msgid "bare repository '%s' is incompatible with fsmonitor" -msgstr "純版本庫 “%s†與 fsmonitor ä¸ç›¸å®¹" +msgstr "純版本庫「%sã€èˆ‡ fsmonitor ä¸ç›¸å®¹" #: fsmonitor-settings.c #, c-format msgid "repository '%s' is incompatible with fsmonitor due to errors" -msgstr "版本庫 “%sâ€ å› éŒ¯èª¤è€Œèˆ‡ fsmonitor ä¸ç›¸å®¹" +msgstr "版本庫「%sã€å› 錯誤而與 fsmonitor ä¸ç›¸å®¹" #: fsmonitor-settings.c #, c-format msgid "remote repository '%s' is incompatible with fsmonitor" -msgstr "é 端版本庫 “%s†與 fsmonitor ä¸ç›¸å®¹" +msgstr "é 端版本庫「%sã€èˆ‡ fsmonitor ä¸ç›¸å®¹" #: fsmonitor-settings.c #, c-format msgid "virtual repository '%s' is incompatible with fsmonitor" -msgstr "虛擬版本庫 “%s†與 fsmonitor ä¸ç›¸å®¹" +msgstr "虛擬版本庫「%sã€èˆ‡ fsmonitor ä¸ç›¸å®¹" #: fsmonitor-settings.c #, c-format msgid "" "socket directory '%s' is incompatible with fsmonitor due to lack of Unix " "sockets support" -msgstr "通訊端 “%sâ€ å› ç¼ºå°‘ Unix 通訊端支æ´ï¼Œè€Œèˆ‡ fsmonitor ä¸ç›¸å®¹" +msgstr "通訊端「%sã€å› 缺少 Unix 通訊端支æ´ï¼Œè€Œèˆ‡ fsmonitor ä¸ç›¸å®¹" #: git.c msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" msgstr "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" -"bare]\n" -" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--config-env=<name>=<envvar>] <command> [<args>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" #: git.c msgid "" @@ -20493,7 +20735,7 @@ msgstr "無法從「%sã€è®€å– SSH ç°½å資料緩è¡å€" #: graph.c #, c-format msgid "ignored invalid color '%.*s' in log.graphColors" -msgstr "已忽略 log.graphColors ä¸ç„¡æ•ˆçš„ “%.*s†色彩" +msgstr "已忽略 log.graphColors ä¸ç„¡æ•ˆçš„「%.*sã€è‰²å½©" #: grep.c msgid "" @@ -20689,14 +20931,14 @@ msgstr "" "è¨å®š `git config advice.ignoredHook false` 來關閉這æ¢è¦å‘Šã€‚" #: http-fetch.c +msgid "not a git repository" +msgstr "䏿˜¯ä¸€å€‹ git 版本庫" + +#: http-fetch.c #, c-format msgid "argument to --packfile must be a valid hash (got '%s')" msgstr "傳入 --packfile çš„åƒæ•¸å¿…é ˆæ˜¯æœ‰æ•ˆçš„é›œæ¹Š (收到 '%s')" -#: http-fetch.c -msgid "not a git repository" -msgstr "䏿˜¯ä¸€å€‹ git 版本庫" - #: http.c #, c-format msgid "negative value for http.postBuffer; defaulting to %d" @@ -20711,6 +20953,10 @@ msgid "Public key pinning not supported with cURL < 7.39.0" msgstr "䏿”¯æ´å…¬é‘°æª”æ¡ˆéŽ–å®šï¼Œå› ç‚º cURL < 7.39.0" #: http.c +msgid "Unknown value for http.proactiveauth" +msgstr "http.proactiveauth 的值未知" + +#: http.c msgid "CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0" msgstr "䏿”¯æ´ CURLSSLOPT_NO_REVOKEï¼Œå› ç‚º cURL < 7.44.0" @@ -20730,6 +20976,14 @@ msgid "Could not set SSL backend to '%s': already set" msgstr "無法將 SSL 後端è¨å®šç‚º '%s':已經è¨å®š" #: http.c +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "ä¸å…許從 http.cookiefile çš„è¨å®šå€¼ã€Œ-ã€è™•è®€å– cookie" + +#: http.c +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "http.cookiefile 空白,忽略 http.savecookies" + +#: http.c #, c-format msgid "" "unable to update url base from redirection:\n" @@ -20813,7 +21067,7 @@ msgstr "sparse:path éŽæ¿¾å™¨æ”¯æ´å·²è¢«åˆªé™¤" #: list-objects-filter-options.c #, c-format msgid "'%s' for 'object:type=<type>' is not a valid object type" -msgstr "“object:type=<type>†的 “%sâ€ ä¸æ˜¯æœ‰æ•ˆçš„ç‰©ä»¶æ ¼å¼" +msgstr "「object:type=<type>ã€çš„「%sã€ä¸æ˜¯æœ‰æ•ˆçš„ç‰©ä»¶æ ¼å¼" #: list-objects-filter-options.c #, c-format @@ -20894,6 +21148,10 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "ä¸èƒ½å»ºç«‹ '%s.lock':%s" +#: log-tree.c +msgid "unable to create temporary object directory" +msgstr "無法建立暫å˜ç‰©ä»¶ç›®éŒ„" + #: loose.c #, c-format msgid "could not write loose object index %s" @@ -20901,8 +21159,8 @@ msgstr "無法寫入鬆散物件索引 %s" #: loose.c #, c-format -msgid "failed to write loose object index %s\n" -msgstr "寫入鬆散物件索引 %s 失敗\n" +msgid "failed to write loose object index %s" +msgstr "寫入鬆散物件索引 %s 失敗" #: ls-refs.c #, c-format @@ -20937,10 +21195,10 @@ msgstr "無法åˆä½µ %s 忍¡çµ„(沒有åˆä½µåŸºåº•)" msgid "Failed to merge submodule %s (commits not present)" msgstr "無法åˆä½µå模組 %s(æäº¤ä¸å˜åœ¨ï¼‰" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "無法åˆä½µå模組 %s (版本庫æå£žï¼‰" +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "錯誤:無法åˆä½µå模組 %s (版本庫æå£žï¼‰" #: merge-ort.c merge-recursive.c #, c-format @@ -20972,14 +21230,15 @@ msgstr "" "無法åˆä½µ %s 忍¡çµ„,但有找到幾個å¯è¡Œçš„åˆä½µæ–¹æ¡ˆï¼š\n" "%s" -#: merge-ort.c merge-recursive.c -msgid "failed to execute internal merge" -msgstr "無法執行內部åˆä½µ" +#: merge-ort.c +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "éŒ¯èª¤ï¼šç„¡æ³•å° %s 執行內部åˆä½µ" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "unable to add %s to database" -msgstr "無法將 %s åŠ é€²è³‡æ–™åº«" +msgid "error: unable to add %s to database" +msgstr "錯誤:無法將 %s åŠ é€²è³‡æ–™åº«" #: merge-ort.c merge-recursive.c #, c-format @@ -21079,15 +21338,15 @@ msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s." msgstr "" "è¡çªï¼ˆé‡æ–°å‘½å/刪除):%1$s 已釿–°å‘½å為 %3$s ä¸çš„ %2$s å»åœ¨ %4$s ä¸è¢«åˆªé™¤ã€‚" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "cannot read object %s" -msgstr "ä¸èƒ½è®€å–物件 %s" +msgid "error: cannot read object %s" +msgstr "錯誤:無法讀å–物件 %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format -msgid "object %s is not a blob" -msgstr "物件 %s 䏿˜¯ä¸€å€‹è³‡æ–™ç‰©ä»¶" +msgid "error: object %s is not a blob" +msgstr "錯誤:物件 %s 䏿˜¯ä¸€å€‹è³‡æ–™ç‰©ä»¶" #: merge-ort.c #, c-format @@ -21243,6 +21502,11 @@ msgstr "ä¸çŸ¥é“å¦‚ä½•è™•ç† %06o %s '%s'" #: merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "無法åˆä½µå模組 %s (版本庫æå£žï¼‰" + +#: merge-recursive.c +#, c-format msgid "Fast-forwarding submodule %s to the following commit:" msgstr "忍¡çµ„ %s 快轉到如下æäº¤ï¼š" @@ -21287,6 +21551,15 @@ msgid "Failed to merge submodule %s (multiple merges found)" msgstr "無法åˆä½µå模組 %s (發ç¾å¤šå€‹åˆä½µï¼‰" #: merge-recursive.c +msgid "failed to execute internal merge" +msgstr "無法執行內部åˆä½µ" + +#: merge-recursive.c +#, c-format +msgid "unable to add %s to database" +msgstr "無法將 %s åŠ é€²è³‡æ–™åº«" + +#: merge-recursive.c #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "錯誤:拒絕éºå¤±æœªè¿½è¹¤æª”案 '%s',而是寫入 %s。" @@ -21401,6 +21674,16 @@ msgstr "" "命å目錄 %4$s->%5$s" #: merge-recursive.c +#, c-format +msgid "cannot read object %s" +msgstr "ä¸èƒ½è®€å–物件 %s" + +#: merge-recursive.c +#, c-format +msgid "object %s is not a blob" +msgstr "物件 %s 䏿˜¯ä¸€å€‹è³‡æ–™ç‰©ä»¶" + +#: merge-recursive.c msgid "modify" msgstr "修改" @@ -21504,10 +21787,6 @@ msgid "malformed line: %s" msgstr "æ©«åˆ—æ ¼å¼éŒ¯èª¤ï¼š%s" #: midx-write.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "å¿½ç•¥ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦" - -#: midx-write.c msgid "could not load pack" msgstr "無法載入包" @@ -21517,6 +21796,24 @@ msgid "could not open index for %s" msgstr "無法開啟 %s 的索引" #: midx-write.c +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "無法將「%sã€link 至「%sã€" + +#: midx-write.c midx.c +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "清ç†ä½æ–¼ %s 的多包索引失敗" + +#: midx-write.c +msgid "cannot write incremental MIDX with bitmap" +msgstr "無法寫入有ä½åœ–çš„å¢žé‡ MIDX" + +#: midx-write.c +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "å¿½ç•¥ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "æ£åœ¨æ–°å¢ž packfile 至多包索引" @@ -21549,14 +21846,30 @@ msgid "refusing to write multi-pack .bitmap without any objects" msgstr "拒絕寫入無任何物件的多包 .bitmap" #: midx-write.c +msgid "unable to create temporary MIDX layer" +msgstr "無法建立暫時的 MIDX 層" + +#: midx-write.c msgid "could not write multi-pack bitmap" msgstr "無法寫入多包ä½åœ–" #: midx-write.c +msgid "unable to open multi-pack-index chain file" +msgstr "無法開啟多å°è£ç´¢å¼•éˆæª”案" + +#: midx-write.c +msgid "unable to rename new multi-pack-index layer" +msgstr "無法更改新多å°è£ç´¢å¼•層的å稱" + +#: midx-write.c msgid "could not write multi-pack-index" msgstr "無法寫入多包索引" #: midx-write.c +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "無法將一個增é‡å¤šå°è£ç´¢å¼•的套件è¨ç‚ºéŽæœŸ" + +#: midx-write.c msgid "Counting referenced objects" msgstr "æ£åœ¨è¨ˆç®—引用物件" @@ -21565,6 +21878,10 @@ msgid "Finding and deleting unreferenced packfiles" msgstr "æ£åœ¨å°‹æ‰¾ä¸¦åˆªé™¤æ²’有引用的 packfile" #: midx-write.c +msgid "cannot repack an incremental multi-pack-index" +msgstr "ç„¡æ³•é‡æ–°å°è£å¢žé‡çš„多å°è£ç´¢å¼•" + +#: midx-write.c msgid "could not start pack-objects" msgstr "ä¸èƒ½é–‹å§‹ pack-objects" @@ -21636,6 +21953,33 @@ msgid "multi-pack-index pack names out of order: '%s' before '%s'" msgstr "多包索引包åç„¡åºï¼š'%s' 在 '%s' 之å‰" #: midx.c +msgid "multi-pack-index chain file too small" +msgstr "多å°è£ç´¢å¼•éˆæª”案éŽå°" + +#: midx.c +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "基礎 MIDX çš„å°è£è¨ˆæ•¸å¤ªé«˜ï¼š%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "基礎 MIDX 的物件計數太高:%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "無法的多å°è£ç´¢å¼•éˆï¼šã€Œ%sã€åˆ—䏿˜¯é›œæ¹Šå€¼" + +#: midx.c +msgid "unable to find all multi-pack index files" +msgstr "找ä¸åˆ°æ‰€æœ‰çš„多å°è£ç´¢å¼•檔案" + +#: midx.c +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "無效的 MIDX 物件ä½ç½®ï¼ŒMIDX 大概有å•題" + +#: midx.c #, c-format msgid "bad pack-int-id: %u (%u total packs)" msgstr "錯的 pack-int-id:%u(共有 %u 個包)" @@ -21658,11 +22002,6 @@ msgid "multi-pack-index large offset out of bounds" msgstr "多包索引的最大å移超出邊界" #: midx.c -#, c-format -msgid "failed to clear multi-pack-index at %s" -msgstr "清ç†ä½æ–¼ %s 的多包索引失敗" - -#: midx.c msgid "multi-pack-index file exists, but failed to parse" msgstr "有 multi-pack-index 檔案,但無法解æž" @@ -21921,6 +22260,16 @@ msgstr "缺少 %s 到 %s çš„æ˜ å°„" #: object-file.c #, c-format +msgid "unable to open %s" +msgstr "ä¸èƒ½é–‹å•Ÿ %s" + +#: object-file.c +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "「%sã€å’Œã€Œ%sã€æª”案內容ä¸åŒ" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "無法寫檔案 %s" @@ -22027,11 +22376,6 @@ msgstr "%s 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„ '%s' 物件" #: object-file.c #, c-format -msgid "unable to open %s" -msgstr "ä¸èƒ½é–‹å•Ÿ %s" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s 的雜湊值ä¸ç¬¦åˆï¼ˆé 期 %s)" @@ -22254,6 +22598,20 @@ msgid "hash mismatch %s" msgstr "雜湊值與 %s ä¸ç¬¦åˆ" #: pack-bitmap-write.c +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "寫入ä½åœ–ç´¢å¼•ä¸æ™‚發ç¾é‡è¤‡é …目:%s" + +#: pack-bitmap-write.c +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "å˜—è©¦å„²å˜æœªé¸å–çš„æäº¤ï¼šã€Œ%sã€" + +#: pack-bitmap-write.c +msgid "too many pseudo-merges" +msgstr "å½åˆä½µéŽå¤š" + +#: pack-bitmap-write.c msgid "trying to write commit not in index" msgstr "嘗試寫入ä¸åœ¨ç´¢å¼•çš„æäº¤" @@ -22272,7 +22630,7 @@ msgstr "ä½åœ–索引檔案æå£žï¼ˆæ¨™é 錯誤)" #: pack-bitmap.c #, c-format msgid "unsupported version '%d' for bitmap index file" -msgstr "ä½åœ–索引檔案的版本 “%dâ€ ä¸æ”¯æ´" +msgstr "ä½åœ–索引檔案的版本「%dã€ä¸æ”¯æ´" #: pack-bitmap.c msgid "corrupted bitmap index file (too short to fit hash cache)" @@ -22283,6 +22641,19 @@ msgid "corrupted bitmap index file (too short to fit lookup table)" msgstr "ä½åœ–索引檔案æå£žï¼ˆä¸å¤ 長,無法置入查詢表)" #: pack-bitmap.c +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "ä½åœ–索引檔案æå£žï¼ˆä¸å¤ 長,無法置入å½åˆä½µè¡¨æ¨™é )" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "ä½åœ–索引檔案æå£žï¼ˆä¸å¤ 長,無法置入å½åˆä½µè¡¨ï¼‰" + +#: pack-bitmap.c +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "ä½åœ–索引檔案æå£žï¼Œå½åˆä½µè¡¨å¤ªçŸ" + +#: pack-bitmap.c #, c-format msgid "duplicate entry in bitmap index: '%s'" msgstr "ä½åœ–ç´¢å¼•ä¸æœ‰é‡è¤‡é …目:「%sã€" @@ -22347,7 +22718,7 @@ msgstr "ä½åœ–查詢表æå£žï¼šæäº¤ç´¢å¼• %u 超出範åœ" #: pack-bitmap.c #, c-format msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\"" -msgstr "ewah ä½åœ–æå£žï¼šæäº¤ “%s†之ä½åœ–的標é éæˆªæ–·" +msgstr "ewah ä½åœ–æå£žï¼šæäº¤ã€Œ%sã€ä¹‹ä½åœ–的標é éæˆªæ–·" #: pack-bitmap.c #, c-format @@ -22397,6 +22768,11 @@ msgstr "ä½åœ–çµæžœä¸æœ‰ä¸ç¬¦é …ç›®" #: pack-bitmap.c #, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "å½åˆä½µç´¢å¼•超出範åœï¼ˆ%<PRIu32> >= %<PRIuMAX>)" + +#: pack-bitmap.c +#, c-format msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" msgstr "在「%2$sã€å°åŒ…,ä½ç§» %3$<PRIuMAX> 的地方找ä¸åˆ°ã€Œ%1$sã€" @@ -22408,7 +22784,7 @@ msgstr "無法å–得「%sã€çš„ç£ç¢Ÿç”¨é‡" #: pack-bitmap.c #, c-format msgid "bitmap file '%s' has invalid checksum" -msgstr "“%s†ä½åœ–檔案的總和檢查碼無效" +msgstr "「%sã€ä½åœ–檔案的總和檢查碼無效" #: pack-mtimes.c #, c-format @@ -22751,7 +23127,7 @@ msgstr "%s:'literal' å’Œ 'glob' ä¸ç›¸å®¹" #: pathspec.c #, c-format msgid "'%s' is outside the directory tree" -msgstr "“%s†在目錄樹之外" +msgstr "「%sã€åœ¨ç›®éŒ„樹之外" #: pathspec.c #, c-format @@ -22848,6 +23224,10 @@ msgid "unable to parse --pretty format" msgstr "ä¸èƒ½è§£æž --pretty æ ¼å¼" #: promisor-remote.c +msgid "lazy fetching disabled; some objects may not be available" +msgstr "延後抓å–已被åœç”¨ï¼›æŸäº›ç‰©ä»¶å¯èƒ½ç„¡æ³•使用" + +#: promisor-remote.c msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: 無法 fork fetch å處ç†ç¨‹åº" @@ -22877,6 +23257,72 @@ msgstr "object-infoï¼šå¼•æ•¸å¾Œé æœŸè¦æœ‰ flush" msgid "Removing duplicate objects" msgstr "æ£åœ¨åˆªé™¤é‡è¤‡ç‰©ä»¶" +#: pseudo-merge.c +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "未能載入 %s çš„å½åˆä½µå¸¸è¦è¡¨ç¤ºå¼ï¼š%s" + +#: pseudo-merge.c +#, c-format +msgid "%s must be non-negative, using default" +msgstr "%s é ˆç‚ºéžè² 數,將採用é è¨å€¼" + +#: pseudo-merge.c +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "%s é ˆä»‹æ–¼ 0 到 1 之間,將採用é è¨å€¼" + +#: pseudo-merge.c +#, c-format +msgid "%s must be positive, using default" +msgstr "%s é ˆç‚ºæ£æ•¸ï¼Œå°‡æŽ¡ç”¨é è¨å€¼" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "å½åˆä½µç¾¤çµ„「%sã€ç¼ºå°‘å¿…é ˆçš„æ¨¡å¼" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "å½åˆä½µç¾¤çµ„「%sã€çš„éžç©©å®šé–¾å€¼ä½æ–¼ç©©å®šè€…之å‰" + +#: pseudo-merge.c +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "來自組態的å½åˆä½µå¸¸è¦è¡¨ç¤ºå¼åŒ…å«å¤ªå¤šçš„æ“·å–群組(最多 %<PRIuMAX> 個)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "延伸å½åˆä½µè®€å–超出範åœï¼ˆ%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "延伸å½åˆä½µé …ç›®éŽçŸï¼ˆ%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "無法在åç§» %2$<PRIuMAX> 處找到æäº¤ %1$s çš„å½åˆä½µ" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "延伸å½åˆä½µæŸ¥è©¢è¶…出範åœï¼ˆ%<PRIu32> >= %<PRIu32>)" + +#: pseudo-merge.c +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "讀å–超出範åœï¼šï¼ˆ%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "ç„¡æ³•è®€å–æäº¤ %s 的延伸å½åˆä½µè¡¨" + #: range-diff.c msgid "could not start `log`" msgstr "ä¸èƒ½å•Ÿå‹• `log`" @@ -22914,7 +23360,7 @@ msgstr "ä¸èƒ½è§£æž '%s' 的日誌" #: reachable.c #, c-format msgid "invalid extra cruft tip: '%s'" -msgstr "無效的é¡å¤–廢棄æäº¤ä¿®è¨‚版:“%sâ€" +msgstr "無效的é¡å¤–廢棄æäº¤ä¿®è¨‚版:「%sã€" #: reachable.c msgid "unable to enumerate additional recent objects" @@ -23106,7 +23552,7 @@ msgstr "éžé 期的 diff 狀態 %c" #: read-cache.c #, c-format msgid "remove '%s'\n" -msgstr "移除 “%sâ€\n" +msgstr "移除「%sã€\n" #: rebase-interactive.c msgid "" @@ -23156,11 +23602,11 @@ msgstr "" "r, reword <æäº¤> = 使用æäº¤ï¼Œä½†ç·¨è¼¯æäº¤èªªæ˜Ž\n" "e, edit <æäº¤> = 使用æäº¤ï¼Œä½†ä¸ç›´æŽ¥ä¿®è£œ (amend) \n" "s, squash <æäº¤> = 使用æäº¤ï¼Œä½†èžåˆè‡³ä¸Šå€‹æäº¤\n" -"f, fixup [-C | -c] <æäº¤> = è·Ÿ “squash†相似,但除éžå‚³å…¥ -C,\n" +"f, fixup [-C | -c] <æäº¤> = 跟「squashã€ç›¸ä¼¼ï¼Œä½†é™¤éžå‚³å…¥ -C,\n" " å¦å‰‡åªä¿ç•™ä¸Šä¸€å€‹æäº¤çš„æ—¥èªŒè¨Šæ¯ã€‚傳入 -C 表示åªä¿ç•™é€™å€‹\n" " æäº¤çš„訊æ¯ï¼›å‚³å…¥ -c 與 -C 功能相åŒï¼Œä½†æœƒé–‹å•Ÿç·¨è¼¯å™¨\n" "x, exec <命令> = 使用 shell 執行命令(這一列的剩餘部分)\n" -"b, break = 在æ¤åœæ¢ï¼ˆä½¿ç”¨ “git rebase --continue†繼續é‡å®šåŸºåº•)\n" +"b, break = 在æ¤åœæ¢ï¼ˆä½¿ç”¨ã€Œgit rebase --continueã€ç¹¼çºŒé‡å®šåŸºåº•)\n" "d, drop <æäº¤> = 移除æäº¤\n" "l, label <標籤> = ç‚ºç›®å‰ HEAD 打上指定åå—æ¨™ç±¤\n" "t, reset <標籤> = é‡è¨ HEAD 到指定標籤\n" @@ -23376,6 +23822,11 @@ msgstr "é æœŸæ ¼å¼ï¼š%%(ahead-behind:<committish>)" #: ref-filter.c #, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "é æœŸæ ¼å¼ï¼š%%(is-base:<committish>)" + +#: ref-filter.c +#, c-format msgid "malformed field name: %.*s" msgstr "æ ¼å¼éŒ¯èª¤çš„æ¬„ä½å:%.*s" @@ -23432,7 +23883,7 @@ msgstr "--format=%.*s ä¸èƒ½å’Œ --pythonã€--shellã€--tcl 一起使用" #: ref-filter.c msgid "failed to run 'describe'" -msgstr "無法執行 “describeâ€" +msgstr "無法執行「describeã€" #: ref-filter.c #, c-format @@ -23550,8 +24001,8 @@ msgstr "" "\n" "\tgit config --global init.defaultBranch <name>\n" "\n" -"除了 “master†外,常用的分支å稱有 “mainâ€, “trunk†以åŠ\n" -"“developmentâ€ã€‚剛建立的分支å¯ä»¥ç”¨é€™å€‹å‘½ä»¤é‡æ–°å‘½å:\n" +"除了「masterã€å¤–,常用的分支å稱有「mainã€,「trunkã€ä»¥åŠ\n" +"「developmentã€ã€‚剛建立的分支å¯ä»¥ç”¨é€™å€‹å‘½ä»¤é‡æ–°å‘½å:\n" "\n" "\tgit branch -m <name>\n" @@ -23586,12 +24037,21 @@ msgid "log for %s is empty" msgstr "%s 的日誌為空" #: refs.c +msgid "refusing to force and skip creation of reflog" +msgstr "拒絕強制並略éŽå»ºç«‹å¼•用日誌" + +#: refs.c #, c-format msgid "refusing to update ref with bad name '%s'" msgstr "拒絕更新有錯誤å稱 '%s' 的引用" #: refs.c #, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "拒絕更新å½å¼•用「%sã€" + +#: refs.c +#, c-format msgid "update_ref failed for ref '%s': %s" msgstr "å°å¼•用 '%s' 執行 update_ref 失敗:%s" @@ -23628,6 +24088,36 @@ msgstr "無法刪除引用 %s:%s" msgid "could not delete references: %s" msgstr "無法刪除引用:%s" +#: refs.c +#, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "完æˆå¼•用移轉的測試執行,å¯ä»¥åœ¨ã€Œ%sã€æ‰¾åˆ°çµæžœ\n" + +#: refs.c +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "無法移除暫時性é·ç§»ç›®éŒ„「%sã€" + +#: refs.c +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "å¯ä»¥åœ¨ã€Œ%sã€æ‰¾åˆ°å·²é·ç§»çš„引用" + +#: refs/files-backend.c refs/reftable-backend.c +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "無法鎖定引用「%sã€ï¼šé 期是指å‘「%sã€çš„符號引用,但這個是一般引用" + +#: refs/files-backend.c +#, c-format +msgid "cannot open directory %s" +msgstr "無法開啟 %s 目錄" + +#: refs/files-backend.c +msgid "Checking references consistency" +msgstr "æ£åœ¨æª¢æŸ¥å¼•用一致性" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -23839,7 +24329,7 @@ msgstr "å”å®šéŒ¯èª¤ï¼šé æœŸæ˜¯ã€Œ<URL> <路徑>ã€ï¼Œä½†ç¼ºå°‘空白" #: remote-curl.c #, c-format msgid "failed to download file at URL '%s'" -msgstr "ç„¡æ³•ä¸‹è¼‰ä½æ–¼ URL “%s†的檔案" +msgstr "ç„¡æ³•ä¸‹è¼‰ä½æ–¼ URL「%sã€çš„æª”案" #: remote-curl.c msgid "git-http-push failed" @@ -23878,12 +24368,12 @@ msgstr "æä¾›äº†ä¸€å€‹ä»¥ä¸Šçš„ uploadpack,使用第一個" #: remote.c #, c-format msgid "unrecognized value transfer.credentialsInUrl: '%s'" -msgstr "數值 transfer.credentialsInUrl 無法è˜åˆ¥ï¼šâ€œ%sâ€" +msgstr "數值 transfer.credentialsInUrl 無法è˜åˆ¥ï¼šã€Œ%sã€" #: remote.c #, c-format msgid "URL '%s' uses plaintext credentials" -msgstr "URL “%s†使用明文憑è‰" +msgstr "URL「%sã€ä½¿ç”¨æ˜Žæ–‡æ†‘è‰" #: remote.c #, c-format @@ -24124,7 +24614,7 @@ msgstr[0] "" #: remote.c msgid "" " (use \"git pull\" if you want to integrate the remote branch with yours)\n" -msgstr " (使用 “git pull†來將é 端分支整åˆé€²æ‚¨çš„分支)\n" +msgstr " (使用「git pullã€ä¾†å°‡é 端分支整åˆé€²æ‚¨çš„分支)\n" #: remote.c #, c-format @@ -24197,7 +24687,7 @@ msgstr "使用之å‰çš„解決方案解決 '%s'。" #: rerere.c #, c-format msgid "cannot unlink stray '%s'" -msgstr "無法刪除失散檔案 “%sâ€" +msgstr "無法刪除失散檔案「%sã€" #: rerere.c #, c-format @@ -24280,7 +24770,7 @@ msgstr "--unpacked=<packfile> å·²ä¸å—支æ´" #: revision.c #, c-format msgid "invalid option '%s' in --stdin mode" -msgstr "在 --stdin 模å¼ä¸‹ï¼Œâ€œ%s†é¸é …無效" +msgstr "在 --stdin 模å¼ä¸‹ï¼Œã€Œ%sã€é¸é …無效" #: revision.c msgid "your current branch appears to be broken" @@ -24394,15 +24884,19 @@ msgstr "åªä¸‹è¼‰æœƒç°½å‡ºçš„分支ä¸ä»‹è³‡æ–™" #: scalar.c msgid "create repository within 'src' directory" -msgstr "在 “src†目錄建立版本庫" +msgstr "在「srcã€ç›®éŒ„建立版本庫" + +#: scalar.c +msgid "specify if tags should be fetched during clone" +msgstr "指定是å¦è¦åœ¨è¤‡è£½éšŽæ®µæŠ“å–æ¨™ç±¤" #: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" #: scalar.c #, c-format @@ -24426,6 +24920,11 @@ msgstr "無法è¨å®šã€Œ%sã€ä¸çš„é 端" #: scalar.c #, c-format +msgid "could not disable tags in '%s'" +msgstr "無法åœç”¨ã€Œ%sã€çš„æ¨™ç±¤" + +#: scalar.c +#, c-format msgid "could not configure '%s'" msgstr "無法è¨å®šã€Œ%sã€" @@ -24464,27 +24963,27 @@ msgstr "--all 或 <enlistment> 但ä¸èƒ½å‚³å…¥å…©è€…" #: scalar.c #, c-format msgid "could not remove stale scalar.repo '%s'" -msgstr "ç„¡æ³•ç§»é™¤éŽæ™‚çš„ scalar.repo “%sâ€" +msgstr "ç„¡æ³•ç§»é™¤éŽæ™‚çš„ scalar.repo「%sã€" #: scalar.c #, c-format msgid "removed stale scalar.repo '%s'" -msgstr "å·²ç§»é™¤éŽæ™‚çš„ scalar.repo “%sâ€" +msgstr "å·²ç§»é™¤éŽæ™‚çš„ scalar.repo「%sã€" #: scalar.c #, c-format msgid "repository at '%s' has different owner" -msgstr "使–¼ “%s†的版本庫有ä¸åŒçš„æ“æœ‰è€…" +msgstr "使–¼ã€Œ%sã€çš„版本庫有ä¸åŒçš„æ“æœ‰è€…" #: scalar.c #, c-format msgid "repository at '%s' has a format issue" -msgstr "使–¼ “%sâ€ çš„ç‰ˆæœ¬åº«æœ‰æ ¼å¼å•題" +msgstr "使–¼ã€Œ%sã€çš„ç‰ˆæœ¬åº«æœ‰æ ¼å¼å•題" #: scalar.c #, c-format msgid "repository not found in '%s'" -msgstr "版本庫ä¸åœ¨ “%sâ€" +msgstr "版本庫ä¸åœ¨ã€Œ%sã€" #: scalar.c #, c-format @@ -25008,12 +25507,12 @@ msgstr "git %sï¼šç„¡æ³•é‡æ–°æ•´ç†ç´¢å¼•" #: sequencer.c #, c-format msgid "'%s' is not a valid label" -msgstr "“%sâ€ ä¸æ˜¯æœ‰æ•ˆçš„æ¨™ç±¤" +msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„æ¨™ç±¤" #: sequencer.c #, c-format msgid "'%s' is not a valid refname" -msgstr "“%sâ€ ä¸æ˜¯æœ‰æ•ˆçš„引用å稱" +msgstr "「%sã€ä¸æ˜¯æœ‰æ•ˆçš„引用å稱" #: sequencer.c #, c-format @@ -25022,8 +25521,56 @@ msgstr "update-ref 需è¦å®Œå…¨é™å®šçš„引用å稱,比如:refs/heads/%s" #: sequencer.c #, c-format +msgid "'%s' does not accept merge commits" +msgstr "「%sã€ä¸æŽ¥å—åˆä½µæäº¤" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"ä¸èƒ½ä½¿ç”¨ã€Œpickã€é¸æ“‡ä¸€å€‹åˆä½µæäº¤ã€‚\n" +"å¦‚æžœä½ æƒ³è¦é‡æ”¾é€™å€‹åˆä½µï¼Œè«‹å°é€™å€‹æäº¤ä½¿ç”¨ã€Œmerge -Cã€ã€‚" + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"「rewordã€ä¸¦ç„¡æ³•使用åˆä½µæäº¤ä½œç‚ºåƒæ•¸ã€‚\n" +"å¦‚æžœä½ å¸Œæœ›åˆä½µä¸¦æ”¹å¯«æäº¤è¨Šæ¯ï¼Œ\n" +"è«‹å°é€™å€‹æäº¤ä½¿ç”¨ã€Œmerge -cã€" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +#: sequencer.c +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"「editã€ä¸¦ç„¡æ³•使用åˆä½µæäº¤ä½œç‚ºåƒæ•¸ã€‚\n" +"å¦‚æžœä½ å¸Œæœ›é‡æ”¾é€™å€‹åˆä½µï¼Œè«‹å°é€™å€‹æäº¤ä½¿ç”¨ã€Œmerge -Cã€ï¼Œ\n" +"並使用「breakã€å–回控制權,\n" +"這樣æ‰èƒ½åŸ·è¡Œã€Œgit commit --amend && git rebase --continueã€ã€‚" + +#: sequencer.c +msgid "cannot squash merge commit into another commit" +msgstr "無法將一個åˆä½µæäº¤å£“æ‰é€²å…¶ä»–æäº¤" + +#: sequencer.c +#, c-format msgid "invalid command '%.*s'" -msgstr "無效的命令 “%.*sâ€" +msgstr "無效的命令「%.*sã€" #: sequencer.c #, c-format @@ -25170,9 +25717,8 @@ msgid "cannot read HEAD" msgstr "ä¸èƒ½è®€å– HEAD" #: sequencer.c -#, c-format -msgid "unable to copy '%s' to '%s'" -msgstr "無法複製 '%s' 至 '%s'" +msgid "could not write commit message file" +msgstr "無法寫入æäº¤è¨Šæ¯æª”案" #: sequencer.c #, c-format @@ -25299,7 +25845,7 @@ msgstr "åˆä½µï¼šç„¡æ³•寫入新索引檔案" #, c-format msgid "" "another 'rebase' process appears to be running; '%s.lock' already exists" -msgstr "似乎有å¦ä¸€å€‹ “rebaseâ€ ç¨‹åºæ£åœ¨é€²è¡Œï¼›â€œ%s.lock†已經å˜åœ¨" +msgstr "似乎有å¦ä¸€å€‹ã€Œrebaseã€ç¨‹åºæ£åœ¨é€²è¡Œï¼›ã€Œ%s.lockã€å·²ç¶“å˜åœ¨" #: sequencer.c #, c-format @@ -25650,6 +26196,24 @@ msgid "failed to stat '%*s%s%s'" msgstr "å–å¾— '%*s%s%s' 狀態(stat)失敗" #: setup.c +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "safe.directory「%sã€ä¸æ˜¯çµ•å°è·¯å¾‘" + +#: setup.c +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"åœ¨ä½æ–¼ã€Œ%sã€çš„ç‰ˆæœ¬åº«åµæ¸¬åˆ°å¯ç–‘所有權\n" +"%sè‹¥è¦æ”¾è¡Œæœ¬ç›®éŒ„,請呼å«ï¼š\n" +"\n" +"\tgit config --global --add safe.directory %s" + +#: setup.c msgid "Unable to read current working directory" msgstr "ä¸èƒ½è®€å–ç›®å‰å·¥ä½œç›®éŒ„" @@ -25674,21 +26238,8 @@ msgstr "" #: setup.c #, c-format -msgid "" -"detected dubious ownership in repository at '%s'\n" -"%sTo add an exception for this directory, call:\n" -"\n" -"\tgit config --global --add safe.directory %s" -msgstr "" -"åœ¨ä½æ–¼ã€Œ%sã€çš„ç‰ˆæœ¬åº«åµæ¸¬åˆ°å¯ç–‘所有權\n" -"%sè‹¥è¦æ”¾è¡Œæœ¬ç›®éŒ„,請呼å«ï¼š\n" -"\n" -"\tgit config --global --add safe.directory %s" - -#: setup.c -#, c-format msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" -msgstr "無法使用 “%s†純版本庫(safe.bareRepository 是 “%sâ€ï¼‰" +msgstr "無法使用「%sã€ç´”版本庫(safe.bareRepository 是「%sã€ï¼‰" #: setup.c #, c-format @@ -26049,6 +26600,16 @@ msgstr "「%sã€å模組 git 目錄在「%.*sã€git 路徑ä¸" #: submodule.c #, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "é æœŸã€Œ%.*sã€ï¼ˆä½æ–¼å模組路徑「%sã€ï¼‰ä¸æ˜¯è±¡å¾µå¼é€£çµ" + +#: submodule.c +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "é æœŸå模組路徑「%sã€ä¸æ˜¯è±¡å¾µå¼é€£çµ" + +#: submodule.c +#, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "䏿”¯æ´å°æœ‰å¤šå€‹å·¥ä½œå€çš„忍¡çµ„ '%s' 執行 relocate_gitdir" @@ -26086,18 +26647,13 @@ msgstr "ls-tree 返回未知返回值 %d" #: symlinks.c #, c-format msgid "failed to lstat '%s'" -msgstr "無法 lstat “%sâ€" +msgstr "無法 lstat「%sã€" #: t/helper/test-bundle-uri.c msgid "no remote configured to get bundle URIs from" msgstr "沒有è¨å®šå¯ä»¥ç”¨ä¾†å–得套件包 URIs çš„é 端" #: t/helper/test-bundle-uri.c -#, c-format -msgid "remote '%s' has no configured URL" -msgstr "“%s†é 端未è¨å®š URL" - -#: t/helper/test-bundle-uri.c msgid "could not get the bundle-uri list" msgstr "無法å–å¾— bundle-uri 清單" @@ -26202,6 +26758,30 @@ msgstr "代符" msgid "command token to send to the server" msgstr "è¦å‚³é€è‡³ä¼ºæœå™¨çš„命令代符" +#: t/unit-tests/unit-test.c +msgid "unit-test [<options>]" +msgstr "unit-test [<options>]" + +#: t/unit-tests/unit-test.c +msgid "immediately exit upon the first failed test" +msgstr "一旦有測試失敗就立刻退出" + +#: t/unit-tests/unit-test.c +msgid "suite[::test]" +msgstr "suite[::test]" + +#: t/unit-tests/unit-test.c +msgid "run only test suite or individual test <suite[::test]>" +msgstr "åªåŸ·è¡Œæ¸¬è©¦å¥—件或單ç¨çš„æ¸¬è©¦ <suite[::test]>" + +#: t/unit-tests/unit-test.c +msgid "suite" +msgstr "suite" + +#: t/unit-tests/unit-test.c +msgid "exclude test suite <suite>" +msgstr "排除測試套件 <suite>" + #: trailer.c #, c-format msgid "running trailer command '%s' failed" @@ -27439,7 +28019,7 @@ msgstr "列舉未追蹤檔案花費 %.2f 秒。" #: wt-status.c msgid "See 'git help status' for information on how to improve this." -msgstr "è«‹åƒé–± “git help status†深入了解如何改善。" +msgstr "è«‹åƒé–±ã€Œgit help statusã€æ·±å…¥äº†è§£å¦‚何改善。" #: wt-status.c #, c-format @@ -27653,6 +28233,10 @@ msgid "--dump-aliases incompatible with other options\n" msgstr "--dump-aliases 和其它é¸é …ä¸ç›¸å®¹\n" #: git-send-email.perl +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "--dump-aliases å’Œ --translate-aliases 互斥\n" + +#: git-send-email.perl msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" @@ -27885,29 +28469,29 @@ msgstr "ç„¡æ³•å‚³é€ %s\n" #: git-send-email.perl #, perl-format -msgid "Dry-Sent %s\n" -msgstr "æ¸¬è©¦åŸ·è¡Œå‚³é€ %s\n" +msgid "Dry-Sent %s" +msgstr "è©¦åŸ·è¡Œå‚³é€ %s" #: git-send-email.perl #, perl-format -msgid "Sent %s\n" -msgstr "æ£å‚³é€ %s\n" +msgid "Sent %s" +msgstr "æ£å‚³é€ %s" #: git-send-email.perl -msgid "Dry-OK. Log says:\n" -msgstr "測試執行æˆåŠŸã€‚æ—¥èªŒèªªï¼š\n" +msgid "Dry-OK. Log says:" +msgstr "試執行æˆåŠŸã€‚æ—¥èªŒèªªï¼š" #: git-send-email.perl -msgid "OK. Log says:\n" -msgstr "OK。日誌說:\n" +msgid "OK. Log says:" +msgstr "OK。日誌說:" #: git-send-email.perl msgid "Result: " msgstr "çµæžœï¼š " #: git-send-email.perl -msgid "Result: OK\n" -msgstr "çµæžœï¼šOK\n" +msgid "Result: OK" +msgstr "çµæžœï¼šOK" #: git-send-email.perl #, perl-format @@ -27942,7 +28526,7 @@ msgstr "(%s) ä¸èƒ½åŸ·è¡Œ '%s'" #: git-send-email.perl #, perl-format msgid "(%s) Malformed output from '%s'" -msgstr "(%s) 從 “%sâ€ è®€åˆ°æ ¼å¼éŒ¯èª¤çš„輸出" +msgstr "(%s) 從「%sã€è®€åˆ°æ ¼å¼éŒ¯èª¤çš„輸出" #: git-send-email.perl #, perl-format @@ -27998,6 +28582,37 @@ msgstr "ç•¥éŽ %s å«å‚™ä»½å¾Œç¶´ '%s'。\n" msgid "Do you really want to send %s? [y|N]: " msgstr "您真的è¦å‚³é€ %s?[y|N]: " +#~ msgid "revision walk setup failed\n" +#~ msgstr "ä¿®è¨‚ç‰ˆéæ·è¨å®šå¤±æ•—\n" + +#, c-format +#~ msgid "unable to parse contact: %s" +#~ msgstr "無法解æžè¯çµ¡åœ°å€ï¼š%s" + +#~ msgid "" +#~ "the add.interactive.useBuiltin setting has been removed!\n" +#~ "See its entry in 'git help config' for details." +#~ msgstr "" +#~ "add.interactive.useBuiltin è¨å®šå·²è¢«ç§»é™¤ï¼\n" +#~ "深入了解請åƒé–± “git help config†ä¸çš„å°æ‡‰æ¢ç›®ã€‚" + +#~ msgid "git archive: Remote with no URL" +#~ msgstr "git archive: 未æä¾›é 端 URL" + +#~ msgid "only one action at a time" +#~ msgstr "一次åªèƒ½æœ‰ä¸€å€‹å‹•作" + +#~ msgid "use [RFC PATCH] instead of [PATCH]" +#~ msgstr "使用 [RFC PATCH] 代替 [PATCH]" + +#, c-format +#~ msgid "no URLs configured for remote '%s'" +#~ msgstr "沒有給é 端版本庫 '%s' è¨å®š URL" + +#, c-format +#~ msgid "remote '%s' has no configured URL" +#~ msgstr "“%s†é 端未è¨å®š URL" + #, c-format #~ msgid "truncating .rej filename to %.*s.rej" #~ msgstr "æ£åœ¨å°‡ .rej 檔案å稱截çŸç‚º %.*s.rej" @@ -28045,9 +28660,6 @@ msgstr "您真的è¦å‚³é€ %s?[y|N]: " #~ msgid "core.commentChar should only be one ASCII character" #~ msgstr "core.commentChar 應該是一個 ASCII å—å…ƒ" -#~ msgid "-x and -X cannot be used together" -#~ msgstr "-x å’Œ -X ä¸èƒ½åŒæ™‚使用" - #~ msgid "" #~ "--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-" #~ "exclude" diff --git a/preload-index.c b/preload-index.c index 63fd35d64b..7926eb09a6 100644 --- a/preload-index.c +++ b/preload-index.c @@ -1,6 +1,9 @@ /* * Copyright (C) 2008 Linus Torvalds */ + +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "pathspec.h" #include "dir.h" @@ -63,7 +63,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *cb UNUSED) { struct cmt_fmt_map *commit_format = NULL; - const char *name; + const char *name, *stripped; char *fmt; int i; @@ -90,15 +90,21 @@ static int git_pretty_formats_config(const char *var, const char *value, commit_formats_len++; } + free((char *)commit_format->name); commit_format->name = xstrdup(name); commit_format->format = CMIT_FMT_USERFORMAT; if (git_config_string(&fmt, var, value)) return -1; - if (skip_prefix(fmt, "format:", &commit_format->user_format)) { + free((char *)commit_format->user_format); + if (skip_prefix(fmt, "format:", &stripped)) { commit_format->is_tformat = 0; - } else if (skip_prefix(fmt, "tformat:", &commit_format->user_format)) { + commit_format->user_format = xstrdup(stripped); + free(fmt); + } else if (skip_prefix(fmt, "tformat:", &stripped)) { commit_format->is_tformat = 1; + commit_format->user_format = xstrdup(stripped); + free(fmt); } else if (strchr(fmt, '%')) { commit_format->is_tformat = 1; commit_format->user_format = fmt; @@ -1770,6 +1776,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ } trailer_out: string_list_clear(&filter_list, 0); + strbuf_release(&kvsepbuf); strbuf_release(&sepbuf); return ret; } @@ -2025,6 +2032,7 @@ void repo_format_commit_message(struct repository *r, free(context.commit_encoding); repo_unuse_commit_buffer(r, commit, context.message); + signature_check_clear(&context.signature_check); } static void pp_header(struct pretty_print_context *pp, @@ -2198,7 +2206,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt, } /* - * pp_handle_indent() prints out the intendation, and + * pp_handle_indent() prints out the indentation, and * the whole line (without the final newline), after * de-tabifying. */ diff --git a/promisor-remote.c b/promisor-remote.c index 317e1b127f..c714f4f007 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -154,6 +154,7 @@ static int promisor_remote_config(const char *var, const char *value, if (!r) return 0; + FREE_AND_NULL(r->partial_clone_filter); return git_config_string(&r->partial_clone_filter, var, value); } @@ -189,6 +190,7 @@ void promisor_remote_clear(struct promisor_remote_config *config) { while (config->promisors) { struct promisor_remote *r = config->promisors; + free(r->partial_clone_filter); config->promisors = config->promisors->next; free(r); } @@ -281,7 +283,7 @@ void promisor_remote_get_direct(struct repository *repo, } for (i = 0; i < remaining_nr; i++) { - if (is_promisor_object(&remaining_oids[i])) + if (is_promisor_object(repo, &remaining_oids[i])) die(_("could not fetch %s from promisor remote"), oid_to_hex(&remaining_oids[i])); } @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "parse.h" #include "environment.h" diff --git a/protocol.c b/protocol.c index 079ba75acf..bae7226ff4 100644 --- a/protocol.c +++ b/protocol.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "environment.h" diff --git a/prune-packed.c b/prune-packed.c index e54daf740a..d1c65ab10e 100644 --- a/prune-packed.c +++ b/prune-packed.c @@ -1,10 +1,12 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" -#include "environment.h" #include "gettext.h" #include "object-store-ll.h" #include "packfile.h" #include "progress.h" #include "prune-packed.h" +#include "repository.h" static struct progress *progress; @@ -22,7 +24,7 @@ static int prune_object(const struct object_id *oid, const char *path, { int *opts = data; - if (!has_object_pack(oid)) + if (!has_object_pack(the_repository, oid)) return 0; if (*opts & PRUNE_PACKED_DRY_RUN) @@ -37,7 +39,7 @@ void prune_packed_objects(int opts) if (opts & PRUNE_PACKED_VERBOSE) progress = start_delayed_progress(_("Removing duplicate objects"), 256); - for_each_loose_file_in_objdir(get_object_directory(), + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), prune_object, NULL, prune_subdir, &opts); /* Ensure we show 100% before finishing progress */ diff --git a/pseudo-merge.c b/pseudo-merge.c index f0fde13c47..bb59965ed2 100644 --- a/pseudo-merge.c +++ b/pseudo-merge.c @@ -87,7 +87,7 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group) { memset(group, 0, sizeof(struct pseudo_merge_group)); - strmap_init_with_options(&group->matches, NULL, 0); + strmap_init_with_options(&group->matches, NULL, 1); group->decay = DEFAULT_PSEUDO_MERGE_DECAY; group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES; @@ -97,6 +97,25 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group) group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE; } +void pseudo_merge_group_release(struct pseudo_merge_group *group) +{ + struct hashmap_iter iter; + struct strmap_entry *e; + + regfree(group->pattern); + free(group->pattern); + + strmap_for_each_entry(&group->matches, &iter, e) { + struct pseudo_merge_matches *matches = e->value; + free(matches->stable); + free(matches->unstable); + free(matches); + } + strmap_clear(&group->matches, 0); + + free(group->merges); +} + static int pseudo_merge_config(const char *var, const char *value, const struct config_context *ctx, void *cb_data) @@ -183,11 +202,12 @@ done: return ret; } -void load_pseudo_merges_from_config(struct string_list *list) +void load_pseudo_merges_from_config(struct repository *r, + struct string_list *list) { struct string_list_item *item; - git_config(pseudo_merge_config, list); + repo_config(r, pseudo_merge_config, list); for_each_string_list_item(item, list) { struct pseudo_merge_group *group = item->util; @@ -201,6 +221,7 @@ void load_pseudo_merges_from_config(struct string_list *list) } static int find_pseudo_merge_group_for_ref(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *_data) @@ -217,6 +238,8 @@ static int find_pseudo_merge_group_for_ref(const char *refname, c = lookup_commit(the_repository, oid); if (!c) return 0; + if (!packlist_find(writer->to_pack, oid)) + return 0; has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, oid); @@ -252,7 +275,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname, matches = strmap_get(&group->matches, group_name.buf); if (!matches) { matches = xcalloc(1, sizeof(*matches)); - strmap_put(&group->matches, strbuf_detach(&group_name, NULL), + strmap_put(&group->matches, group_name.buf, matches); } @@ -357,8 +380,10 @@ static void select_pseudo_merges_1(struct bitmap_writer *writer, p = commit_list_append(c, p); } while (j % group->stable_size); - bitmap_writer_push_commit(writer, merge, 1); - writer->pseudo_merges_nr++; + if (merge->parents) { + bitmap_writer_push_commit(writer, merge, 1); + writer->pseudo_merges_nr++; + } } /* make up to group->max_merges pseudo merges for unstable commits */ @@ -398,8 +423,9 @@ static void select_pseudo_merges_1(struct bitmap_writer *writer, p = commit_list_append(c, p); } - bitmap_writer_push_commit(writer, merge, 1); - writer->pseudo_merges_nr++; + if (merge->parents) { + bitmap_writer_push_commit(writer, merge, 1); + writer->pseudo_merges_nr++; } if (end >= matches->unstable_nr) break; } @@ -423,8 +449,7 @@ static void sort_pseudo_merge_matches(struct pseudo_merge_matches *matches) QSORT(matches->unstable, matches->unstable_nr, commit_date_cmp); } -void select_pseudo_merges(struct bitmap_writer *writer, - struct commit **commits, size_t commits_nr) +void select_pseudo_merges(struct bitmap_writer *writer) { struct progress *progress = NULL; uint32_t i; diff --git a/pseudo-merge.h b/pseudo-merge.h index 2aca01d056..29df8a32ec 100644 --- a/pseudo-merge.h +++ b/pseudo-merge.h @@ -10,6 +10,7 @@ struct commit; struct string_list; struct bitmap_index; struct bitmap_writer; +struct repository; /* * A pseudo-merge group tracks the set of non-bitmapped reference tips @@ -50,6 +51,8 @@ struct pseudo_merge_group { timestamp_t stable_threshold; }; +void pseudo_merge_group_release(struct pseudo_merge_group *group); + struct pseudo_merge_matches { struct commit **stable; struct commit **unstable; @@ -72,7 +75,7 @@ struct pseudo_merge_matches { * entry keys are the pseudo-merge group names, and the values are * pointers to the pseudo_merge_group structure itself. */ -void load_pseudo_merges_from_config(struct string_list *list); +void load_pseudo_merges_from_config(struct repository *r, struct string_list *list); /* * A pseudo-merge commit index (pseudo_merge_commit_idx) maps a @@ -94,8 +97,7 @@ struct pseudo_merge_commit_idx { * * Optionally shows a progress meter. */ -void select_pseudo_merges(struct bitmap_writer *writer, - struct commit **commits, size_t commits_nr); +void select_pseudo_merges(struct bitmap_writer *writer); /* * Represents a serialized view of a file containing pseudo-merge(s) diff --git a/range-diff.c b/range-diff.c index 5f01605550..10885ba301 100644 --- a/range-diff.c +++ b/range-diff.c @@ -450,8 +450,10 @@ static void output_pair_header(struct diff_options *diffopt, } static struct userdiff_driver section_headers = { - .funcname = { "^ ## (.*) ##$\n" - "^.?@@ (.*)$", REG_EXTENDED } + .funcname = { + .pattern = "^ ## (.*) ##$\n^.?@@ (.*)$", + .cflags = REG_EXTENDED, + }, }; static struct diff_filespec *get_filespec(const char *name, const char *p) @@ -478,7 +480,7 @@ static void patch_diff(const char *a, const char *b, diff_flush(diffopt); } -static struct strbuf *output_prefix_cb(struct diff_options *opt UNUSED, void *data) +static const char *output_prefix_cb(struct diff_options *opt UNUSED, void *data) { return data; } @@ -506,7 +508,7 @@ static void output(struct string_list *a, struct string_list *b, opts.flags.suppress_hunk_header_line_count = 1; opts.output_prefix = output_prefix_cb; strbuf_addstr(&indent, " "); - opts.output_prefix_data = &indent; + opts.output_prefix_data = indent.buf; diff_setup_done(&opts); /* diff --git a/reachable.c b/reachable.c index 46613a6bb6..ecf7ccf504 100644 --- a/reachable.c +++ b/reachable.c @@ -79,7 +79,7 @@ static void add_rebase_files(struct rev_info *revs) free_worktrees(worktrees); } -static int add_one_ref(const char *path, const struct object_id *oid, +static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { struct rev_info *revs = (struct rev_info *)cb_data; @@ -239,7 +239,7 @@ static int want_recent_object(struct recent_data *data, const struct object_id *oid) { if (data->ignore_in_core_kept_packs && - has_object_kept_pack(oid, IN_CORE_KEEP_PACKS)) + has_object_kept_pack(data->revs->repo, oid, IN_CORE_KEEP_PACKS)) return 0; return 1; } @@ -324,7 +324,7 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs, if (ignore_in_core_kept_packs) flags |= FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS; - r = for_each_packed_object(add_recent_packed, &data, flags); + r = for_each_packed_object(revs->repo, add_recent_packed, &data, flags); done: oidset_clear(&data.extra_recent_oids); diff --git a/read-cache-ll.h b/read-cache-ll.h index e0e39607ef..71b49d9af4 100644 --- a/read-cache-ll.h +++ b/read-cache-ll.h @@ -151,7 +151,7 @@ enum sparse_index_mode { /* * The index has already been collapsed to sparse directories - * whereever possible. + * wherever possible. */ INDEX_COLLAPSED, @@ -196,7 +196,7 @@ struct index_state { * * If the variable won't be used again, use release_index() to free() * its resources. If it needs to be used again use discard_index(), - * which does the same thing, but will use use index_state_init() at + * which does the same thing, but will use index_state_init() at * the end. The discard_index() will use its own "istate->repo" as the * "r" argument to index_state_init() in that case. */ diff --git a/read-cache.c b/read-cache.c index 48bf24f87c..01d0b3ad22 100644 --- a/read-cache.c +++ b/read-cache.c @@ -31,6 +31,7 @@ #include "path.h" #include "preload-index.h" #include "read-cache.h" +#include "repository.h" #include "resolve-undo.h" #include "revision.h" #include "strbuf.h" @@ -1945,7 +1946,7 @@ static void tweak_untracked_cache(struct index_state *istate) static void tweak_split_index(struct index_state *istate) { - switch (git_config_get_split_index()) { + switch (repo_config_get_split_index(the_repository)) { case -1: /* unset: do nothing */ break; case 0: /* false */ @@ -2187,6 +2188,7 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con if (err) die(_("unable to join load_cache_entries thread: %s"), strerror(err)); mem_pool_combine(istate->ce_mem_pool, p->ce_mem_pool); + free(p->ce_mem_pool); consumed += p->consumed; } @@ -2267,7 +2269,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist) src_offset = sizeof(*hdr); - if (git_config_get_index_threads(&nr_threads)) + if (repo_config_get_index_threads(the_repository, &nr_threads)) nr_threads = 1; /* TODO: does creating more threads than cores help? */ @@ -2787,7 +2789,7 @@ static int record_eoie(void) * used for threading is written by default if the user * explicitly requested threaded index reads. */ - return !git_config_get_index_threads(&val) && val != 1; + return !repo_config_get_index_threads(the_repository, &val) && val != 1; } static int record_ieot(void) @@ -2802,7 +2804,7 @@ static int record_ieot(void) * written by default if the user explicitly requested * threaded index reads. */ - return !git_config_get_index_threads(&val) && val != 1; + return !repo_config_get_index_threads(the_repository, &val) && val != 1; } enum write_extensions { @@ -2840,8 +2842,9 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, int csum_fsync_flag; int ieot_entries = 1; struct index_entry_offset_table *ieot = NULL; - int nr, nr_threads; struct repository *r = istate->repo; + struct strbuf sb = STRBUF_INIT; + int nr, nr_threads, ret; f = hashfd(tempfile->fd, tempfile->filename.buf); @@ -2875,7 +2878,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, hashwrite(f, &hdr, sizeof(hdr)); - if (!HAVE_THREADS || git_config_get_index_threads(&nr_threads)) + if (!HAVE_THREADS || repo_config_get_index_threads(the_repository, &nr_threads)) nr_threads = 1; if (nr_threads != 1 && record_ieot()) { @@ -2962,8 +2965,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, strbuf_release(&previous_name_buf); if (err) { - free(ieot); - return err; + ret = err; + goto out; } offset = hashfile_total(f); @@ -2985,20 +2988,20 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, * index. */ if (ieot) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); write_ieot_extension(&sb, ieot); err = write_index_ext_header(f, eoie_c, CACHE_EXT_INDEXENTRYOFFSETTABLE, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - free(ieot); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION && istate->split_index) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); if (istate->sparse_index) die(_("cannot write split index for a sparse index")); @@ -3007,59 +3010,66 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, write_index_ext_header(f, eoie_c, CACHE_EXT_LINK, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (write_extensions & WRITE_CACHE_TREE_EXTENSION && !drop_cache_tree && istate->cache_tree) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); cache_tree_write(&sb, istate->cache_tree); err = write_index_ext_header(f, eoie_c, CACHE_EXT_TREE, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION && istate->resolve_undo) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); resolve_undo_write(&sb, istate->resolve_undo); err = write_index_ext_header(f, eoie_c, CACHE_EXT_RESOLVE_UNDO, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION && istate->untracked) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); write_untracked_extension(&sb, istate->untracked); err = write_index_ext_header(f, eoie_c, CACHE_EXT_UNTRACKED, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (write_extensions & WRITE_FSMONITOR_EXTENSION && istate->fsmonitor_last_update) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); write_fsmonitor_extension(&sb, istate); err = write_index_ext_header(f, eoie_c, CACHE_EXT_FSMONITOR, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } if (istate->sparse_index) { - if (write_index_ext_header(f, eoie_c, CACHE_EXT_SPARSE_DIRECTORIES, 0) < 0) - return -1; + if (write_index_ext_header(f, eoie_c, CACHE_EXT_SPARSE_DIRECTORIES, 0) < 0) { + ret = -1; + goto out; + } } /* @@ -3069,14 +3079,15 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, * when loading the shared index. */ if (eoie_c) { - struct strbuf sb = STRBUF_INIT; + strbuf_reset(&sb); write_eoie_extension(&sb, eoie_c, offset); err = write_index_ext_header(f, NULL, CACHE_EXT_ENDOFINDEXENTRIES, sb.len) < 0; hashwrite(f, sb.buf, sb.len); - strbuf_release(&sb); - if (err) - return -1; + if (err) { + ret = -1; + goto out; + } } csum_fsync_flag = 0; @@ -3085,13 +3096,16 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, finalize_hashfile(f, istate->oid.hash, FSYNC_COMPONENT_INDEX, CSUM_HASH_IN_STREAM | csum_fsync_flag); + f = NULL; if (close_tempfile_gently(tempfile)) { - error(_("could not close '%s'"), get_tempfile_path(tempfile)); - return -1; + ret = error(_("could not close '%s'"), get_tempfile_path(tempfile)); + goto out; + } + if (stat(get_tempfile_path(tempfile), &st)) { + ret = -1; + goto out; } - if (stat(get_tempfile_path(tempfile), &st)) - return -1; istate->timestamp.sec = (unsigned int)st.st_mtime; istate->timestamp.nsec = ST_MTIME_NSEC(st); trace_performance_since(start, "write index, changed mask = %x", istate->cache_changed); @@ -3105,7 +3119,15 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, trace2_data_intmax("index", the_repository, "write/cache_nr", istate->cache_nr); - return 0; + ret = 0; + +out: + if (f) + free_hashfile(f); + strbuf_release(&sb); + free(eoie_c); + free(ieot); + return ret; } void set_alternate_index_output(const char *name) @@ -3156,9 +3178,9 @@ static int do_write_locked_index(struct index_state *istate, else ret = close_lock_file_gently(lock); - run_hooks_l("post-index-change", - istate->updated_workdir ? "1" : "0", - istate->updated_skipworktree ? "1" : "0", NULL); + run_hooks_l(the_repository, "post-index-change", + istate->updated_workdir ? "1" : "0", + istate->updated_skipworktree ? "1" : "0", NULL); istate->updated_workdir = 0; istate->updated_skipworktree = 0; @@ -3176,18 +3198,24 @@ static int write_split_index(struct index_state *istate, return ret; } -static const char *shared_index_expire = "2.weeks.ago"; - static unsigned long get_shared_index_expire_date(void) { static unsigned long shared_index_expire_date; static int shared_index_expire_date_prepared; if (!shared_index_expire_date_prepared) { - git_config_get_expiry("splitindex.sharedindexexpire", - &shared_index_expire); + const char *shared_index_expire = "2.weeks.ago"; + char *value = NULL; + + repo_config_get_expiry(the_repository, "splitindex.sharedindexexpire", + &value); + if (value) + shared_index_expire = value; + shared_index_expire_date = approxidate(shared_index_expire); shared_index_expire_date_prepared = 1; + + free(value); } return shared_index_expire_date; @@ -3213,10 +3241,11 @@ static int should_delete_shared_index(const char *shared_index_path) static int clean_shared_index_files(const char *current_hex) { struct dirent *de; - DIR *dir = opendir(get_git_dir()); + DIR *dir = opendir(repo_get_git_dir(the_repository)); if (!dir) - return error_errno(_("unable to open git dir: %s"), get_git_dir()); + return error_errno(_("unable to open git dir: %s"), + repo_get_git_dir(the_repository)); while ((de = readdir(dir)) != NULL) { const char *sha1_hex; @@ -3275,7 +3304,7 @@ static const int default_max_percent_split_change = 20; static int too_many_not_shared_entries(struct index_state *istate) { int i, not_shared = 0; - int max_split = git_config_get_max_percent_split_change(); + int max_split = repo_config_get_max_percent_split_change(the_repository); switch (max_split) { case -1: @@ -3306,8 +3335,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, int new_shared_index, ret, test_split_index_env; struct split_index *si = istate->split_index; - if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0)) - cache_tree_verify(the_repository, istate); + if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0) && + cache_tree_verify(the_repository, istate) < 0) + return -1; if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) { if (flags & COMMIT_LOCK) @@ -11,7 +11,7 @@ * The callers that care if (any) rebase is requested should say * if (REBASE_TRUE <= rebase_parse_value(string)) * - * The callers that want to differenciate an unrecognised value and + * The callers that want to differentiate an unrecognised value and * false can do so by treating _INVALID and _FALSE differently. */ enum rebase_type rebase_parse_value(const char *value) diff --git a/ref-filter.c b/ref-filter.c index 8c5e673fc0..84c6036107 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -13,6 +13,7 @@ #include "object-name.h" #include "object-store-ll.h" #include "oid-array.h" +#include "repo-settings.h" #include "repository.h" #include "commit.h" #include "mailmap.h" @@ -75,11 +76,11 @@ struct refname_atom { int lstrip, rstrip; }; -static struct ref_trailer_buf { +struct ref_trailer_buf { struct string_list filter_list; struct strbuf sepbuf; struct strbuf kvsepbuf; -} ref_trailer_buf = {STRING_LIST_INIT_NODUP, STRBUF_INIT, STRBUF_INIT}; +}; static struct expand_data { struct object_id oid; @@ -169,6 +170,7 @@ enum atom_type { ATOM_ELSE, ATOM_REST, ATOM_AHEADBEHIND, + ATOM_ISBASE, }; /* @@ -200,6 +202,7 @@ static struct used_atom { enum { C_BARE, C_BODY, C_BODY_DEP, C_LENGTH, C_LINES, C_SIG, C_SUB, C_SUB_SANITIZE, C_TRAILERS } option; struct process_trailer_options trailer_opts; + struct ref_trailer_buf *trailer_buf; unsigned int nlines; } contents; struct { @@ -231,7 +234,7 @@ static struct used_atom { enum { S_BARE, S_GRADE, S_SIGNER, S_KEY, S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option; } signature; - const char **describe_args; + struct strvec describe_args; struct refname_atom refname; char *head; } u; @@ -565,21 +568,36 @@ static int trailers_atom_parser(struct ref_format *format UNUSED, atom->u.contents.trailer_opts.no_divider = 1; if (arg) { - const char *argbuf = xstrfmt("%s)", arg); + char *argbuf = xstrfmt("%s)", arg); + const char *arg = argbuf; char *invalid_arg = NULL; + struct ref_trailer_buf *tb; + + /* + * Do not inline these directly into the used_atom struct! + * When we parse them in format_set_trailers_options(), + * we will make pointer references directly to them, + * which will not survive a realloc() of the used_atom list. + * They must be allocated in a separate, stable struct. + */ + atom->u.contents.trailer_buf = tb = xmalloc(sizeof(*tb)); + string_list_init_dup(&tb->filter_list); + strbuf_init(&tb->sepbuf, 0); + strbuf_init(&tb->kvsepbuf, 0); if (format_set_trailers_options(&atom->u.contents.trailer_opts, - &ref_trailer_buf.filter_list, - &ref_trailer_buf.sepbuf, - &ref_trailer_buf.kvsepbuf, - &argbuf, &invalid_arg)) { + &tb->filter_list, + &tb->sepbuf, &tb->kvsepbuf, + &arg, &invalid_arg)) { if (!invalid_arg) strbuf_addf(err, _("expected %%(trailers:key=<value>)")); else strbuf_addf(err, _("unknown %%(trailers) argument: %s"), invalid_arg); - free((char *)invalid_arg); + free(invalid_arg); + free(argbuf); return -1; } + free(argbuf); } atom->u.contents.option = C_TRAILERS; return 0; @@ -676,7 +694,7 @@ static int describe_atom_parser(struct ref_format *format UNUSED, struct used_atom *atom, const char *arg, struct strbuf *err) { - struct strvec args = STRVEC_INIT; + strvec_init(&atom->u.describe_args); for (;;) { int found = 0; @@ -685,13 +703,12 @@ static int describe_atom_parser(struct ref_format *format UNUSED, if (!arg || !*arg) break; - found = describe_atom_option_parser(&args, &arg, err); + found = describe_atom_option_parser(&atom->u.describe_args, &arg, err); if (found < 0) return found; if (!found) return err_bad_arg(err, "describe", bad_arg); } - atom->u.describe_args = strvec_detach(&args); return 0; } @@ -742,8 +759,7 @@ static int person_name_atom_parser(struct ref_format *format UNUSED, return 0; } -static int email_atom_option_parser(struct used_atom *atom, - const char **arg, struct strbuf *err) +static int email_atom_option_parser(const char **arg) { if (!*arg) return EO_RAW; @@ -761,7 +777,7 @@ static int person_email_atom_parser(struct ref_format *format UNUSED, const char *arg, struct strbuf *err) { for (;;) { - int opt = email_atom_option_parser(atom, &arg, err); + int opt = email_atom_option_parser(&arg); const char *bad_arg = arg; if (opt < 0) @@ -891,6 +907,23 @@ static int ahead_behind_atom_parser(struct ref_format *format, return 0; } +static int is_base_atom_parser(struct ref_format *format, + struct used_atom *atom UNUSED, + const char *arg, struct strbuf *err) +{ + struct string_list_item *item; + + if (!arg) + return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)")); + + item = string_list_append(&format->is_base_tips, arg); + item->util = lookup_commit_reference_by_name(arg); + if (!item->util) + die("failed to find '%s'", arg); + + return 0; +} + static int head_atom_parser(struct ref_format *format UNUSED, struct used_atom *atom, const char *arg, struct strbuf *err) @@ -956,6 +989,7 @@ static struct { [ATOM_ELSE] = { "else", SOURCE_NONE }, [ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser }, [ATOM_AHEADBEHIND] = { "ahead-behind", SOURCE_OTHER, FIELD_STR, ahead_behind_atom_parser }, + [ATOM_ISBASE] = { "is-base", SOURCE_OTHER, FIELD_STR, is_base_atom_parser }, /* * Please update $__git_ref_fieldlist in git-completion.bash * when you add new atoms @@ -968,6 +1002,7 @@ struct ref_formatting_stack { struct ref_formatting_stack *prev; struct strbuf output; void (*at_end)(struct ref_formatting_stack **stack); + void (*at_end_data_free)(void *data); void *at_end_data; }; @@ -1136,6 +1171,8 @@ static void pop_stack_element(struct ref_formatting_stack **stack) if (prev) strbuf_addbuf(&prev->output, ¤t->output); strbuf_release(¤t->output); + if (current->at_end_data_free) + current->at_end_data_free(current->at_end_data); free(current); *stack = prev; } @@ -1195,15 +1232,13 @@ static void if_then_else_handler(struct ref_formatting_stack **stack) } *stack = cur; - free(if_then_else); } static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, struct strbuf *err UNUSED) { struct ref_formatting_stack *new_stack; - struct if_then_else *if_then_else = xcalloc(1, - sizeof(struct if_then_else)); + struct if_then_else *if_then_else = xcalloc(1, sizeof(*if_then_else)); if_then_else->str = atomv->atom->u.if_then_else.str; if_then_else->cmp_status = atomv->atom->u.if_then_else.cmp_status; @@ -1212,6 +1247,7 @@ static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state new_stack = state->stack; new_stack->at_end = if_then_else_handler; new_stack->at_end_data = if_then_else; + new_stack->at_end_data_free = free; return 0; } @@ -1628,6 +1664,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam timestamp = parse_timestamp(eoemail + 2, &zone, 10); if (timestamp == TIME_MAX) goto bad; + errno = 0; tz = strtol(zone, NULL, 10); if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE) goto bad; @@ -1814,16 +1851,10 @@ static void find_subpos(const char *buf, size_t *nonsiglen, const char **sig, size_t *siglen) { - struct strbuf payload = STRBUF_INIT; - struct strbuf signature = STRBUF_INIT; const char *eol; const char *end = buf + strlen(buf); const char *sigstart; - /* parse signature first; we might not even have a subject line */ - parse_signature(buf, end - buf, &payload, &signature); - strbuf_release(&payload); - /* skip past header until we hit empty line */ while (*buf && *buf != '\n') { eol = strchrnul(buf, '\n'); @@ -1834,8 +1865,10 @@ static void find_subpos(const char *buf, /* skip any empty lines */ while (*buf == '\n') buf++; - *sig = strbuf_detach(&signature, siglen); + /* parse signature first; we might not even have a subject line */ sigstart = buf + parse_signed_buffer(buf, strlen(buf)); + *sig = sigstart; + *siglen = end - *sig; /* subject is first non-empty line */ *sub = buf; @@ -1910,7 +1943,7 @@ static void grab_describe_values(struct atom_value *val, int deref, cmd.git_cmd = 1; strvec_push(&cmd.args, "describe"); - strvec_pushv(&cmd.args, atom->u.describe_args); + strvec_pushv(&cmd.args, atom->u.describe_args.v); strvec_push(&cmd.args, oid_to_hex(&commit->object.oid)); if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) { error(_("failed to run 'describe'")); @@ -1993,16 +2026,23 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp v->s = strbuf_detach(&s, NULL); } else if (atom->u.contents.option == C_TRAILERS) { struct strbuf s = STRBUF_INIT; + const char *msg; + char *to_free = NULL; + + if (siglen) + msg = to_free = xmemdupz(subpos, sigpos - subpos); + else + msg = subpos; /* Format the trailer info according to the trailer_opts given */ - format_trailers_from_commit(&atom->u.contents.trailer_opts, subpos, &s); + format_trailers_from_commit(&atom->u.contents.trailer_opts, msg, &s); + free(to_free); v->s = strbuf_detach(&s, NULL); } else if (atom->u.contents.option == C_BARE) v->s = xstrdup(subpos); } - free((void *)sigpos); } /* @@ -2141,7 +2181,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname) if (atom->option == R_SHORT) return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), refname, - warn_ambiguous_refs); + repo_settings_get_warn_ambiguous_refs(the_repository)); else if (atom->option == R_LSTRIP) return lstrip_ref_components(refname, atom->lstrip); else if (atom->option == R_RSTRIP) @@ -2200,7 +2240,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname, const char *merge; merge = remote_ref_for_branch(branch, atom->u.remote_ref.push); - *s = xstrdup(merge ? merge : ""); + *s = merge ? merge : xstrdup(""); } else BUG("unhandled RR_* enum"); } @@ -2340,9 +2380,16 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) int i; struct object_info empty = OBJECT_INFO_INIT; int ahead_behind_atoms = 0; + int is_base_atoms = 0; CALLOC_ARRAY(ref->value, used_atom_cnt); + /** + * NEEDSWORK: The following code might be unnecessary if all codepaths + * that call populate_value() populates the symref member of ref_array_item + * like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath + * that calls populate_value() without first populating symref. + */ if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) { ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository), ref->refname, @@ -2483,6 +2530,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) v->s = xstrdup(""); } continue; + } else if (atom_type == ATOM_ISBASE) { + if (ref->is_base && ref->is_base[is_base_atoms]) { + v->s = xstrfmt("(%s)", ref->is_base[is_base_atoms]); + free(ref->is_base[is_base_atoms]); + } else { + v->s = xstrdup(""); + } + is_base_atoms++; + continue; } else continue; @@ -2783,7 +2839,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname) return ref_kind_from_refname(refname); } -static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid, +static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid, int flag, struct ref_filter *filter) { struct ref_array_item *ref; @@ -2852,6 +2908,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct ref->commit = commit; ref->flag = flag; ref->kind = kind; + ref->symref = xstrdup_or_null(referent); return ref; } @@ -2865,12 +2922,12 @@ struct ref_filter_cbdata { * A call-back given to for_each_ref(). Filter refs and keep them for * later object processing. */ -static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data) +static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data) { struct ref_filter_cbdata *ref_cbdata = cb_data; struct ref_array_item *ref; - ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter); + ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter); if (ref) ref_array_append(ref_cbdata->array, ref); @@ -2888,6 +2945,7 @@ static void free_array_item(struct ref_array_item *item) free(item->value); } free(item->counts); + free(item->is_base); free(item); } @@ -2900,13 +2958,13 @@ struct ref_filter_and_format_cbdata { } internal; }; -static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data) +static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data) { struct ref_filter_and_format_cbdata *ref_cbdata = cb_data; struct ref_array_item *ref; struct strbuf output = STRBUF_INIT, err = STRBUF_INIT; - ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter); + ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter); if (!ref) return 0; @@ -2948,6 +3006,19 @@ void ref_array_clear(struct ref_array *array) struct used_atom *atom = &used_atom[i]; if (atom->atom_type == ATOM_HEAD) free(atom->u.head); + else if (atom->atom_type == ATOM_DESCRIBE) + strvec_clear(&atom->u.describe_args); + else if (atom->atom_type == ATOM_TRAILERS || + (atom->atom_type == ATOM_CONTENTS && + atom->u.contents.option == C_TRAILERS)) { + struct ref_trailer_buf *tb = atom->u.contents.trailer_buf; + if (tb) { + string_list_clear(&tb->filter_list, 0); + strbuf_release(&tb->sepbuf); + strbuf_release(&tb->kvsepbuf); + free(tb); + } + } free((char *)atom->name); } FREE_AND_NULL(used_atom); @@ -3052,6 +3123,49 @@ void filter_ahead_behind(struct repository *r, free(commits); } +void filter_is_base(struct repository *r, + struct ref_format *format, + struct ref_array *array) +{ + struct commit **bases; + size_t bases_nr = 0; + struct ref_array_item **back_index; + + if (!format->is_base_tips.nr || !array->nr) + return; + + CALLOC_ARRAY(back_index, array->nr); + CALLOC_ARRAY(bases, array->nr); + + for (size_t i = 0; i < array->nr; i++) { + const char *name = array->items[i]->refname; + struct commit *c = lookup_commit_reference_by_name_gently(name, 1); + + CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr); + + if (!c) + continue; + + back_index[bases_nr] = array->items[i]; + bases[bases_nr] = c; + bases_nr++; + } + + for (size_t i = 0; i < format->is_base_tips.nr; i++) { + struct commit *tip = format->is_base_tips.items[i].util; + int base_index = get_branch_base_for_tip(r, tip, bases, bases_nr); + + if (base_index < 0) + continue; + + /* Store the string for use in output later. */ + back_index[base_index]->is_base[i] = xstrdup(format->is_base_tips.items[i].string); + } + + free(back_index); + free(bases); +} + static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data) { int ret = 0; @@ -3130,22 +3244,42 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int return ret; } +struct ref_sorting { + struct ref_sorting *next; + int atom; /* index into used_atom array (internal) */ + enum ref_sorting_order sort_flags; +}; + static inline int can_do_iterative_format(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format) { /* + * Reference backends sort patterns lexicographically by refname, so if + * the sorting options ask for exactly that we are able to do iterative + * formatting. + * + * Note that we do not have to worry about multiple name patterns, + * either. Those get sorted and deduplicated eventually in + * `refs_for_each_fullref_in_prefixes()`, so we return names in the + * correct ordering here, too. + */ + if (sorting && (sorting->next || + sorting->sort_flags || + used_atom[sorting->atom].atom_type != ATOM_REFNAME)) + return 0; + + /* * Filtering & formatting results within a single ref iteration * callback is not compatible with options that require * post-processing a filtered ref_array. These include: * - filtering on reachability - * - sorting the filtered results * - including ahead-behind information in the formatted output */ return !(filter->reachable_from || filter->unreachable_from || - sorting || - format->bases.nr); + format->bases.nr || + format->is_base_tips.nr); } void filter_and_format_refs(struct ref_filter *filter, unsigned int type, @@ -3169,6 +3303,7 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type, struct ref_array array = { 0 }; filter_refs(&array, filter, type); filter_ahead_behind(the_repository, format, &array); + filter_is_base(the_repository, format, &array); ref_array_sort(sorting, &array); print_formatted_ref_array(&array, format); ref_array_clear(&array); @@ -3200,12 +3335,6 @@ static int memcasecmp(const void *vs1, const void *vs2, size_t n) return 0; } -struct ref_sorting { - struct ref_sorting *next; - int atom; /* index into used_atom array (internal) */ - enum ref_sorting_order sort_flags; -}; - static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b) { struct atom_value *va, *vb; @@ -3508,3 +3637,16 @@ void ref_filter_clear(struct ref_filter *filter) free_commit_list(filter->unreachable_from); ref_filter_init(filter); } + +void ref_format_init(struct ref_format *format) +{ + struct ref_format blank = REF_FORMAT_INIT; + memcpy(format, &blank, sizeof(blank)); +} + +void ref_format_clear(struct ref_format *format) +{ + string_list_clear(&format->bases, 0); + string_list_clear(&format->is_base_tips, 0); + ref_format_init(format); +} diff --git a/ref-filter.h b/ref-filter.h index 27ae1aa0d1..754038ab07 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -48,6 +48,7 @@ struct ref_array_item { struct commit *commit; struct atom_value *value; struct ahead_behind_count **counts; + char **is_base; char refname[FLEX_ARRAY]; }; @@ -101,6 +102,9 @@ struct ref_format { /* List of bases for ahead-behind counts. */ struct string_list bases; + /* List of bases for is-base indicators. */ + struct string_list is_base_tips; + struct { int max_count; int omit_empty; @@ -114,6 +118,7 @@ struct ref_format { #define REF_FORMAT_INIT { \ .use_color = -1, \ .bases = STRING_LIST_INIT_DUP, \ + .is_base_tips = STRING_LIST_INIT_DUP, \ } /* Macros for checking --merged and --no-merged options */ @@ -203,7 +208,20 @@ void filter_ahead_behind(struct repository *r, struct ref_format *format, struct ref_array *array); +/* + * If the provided format includes is-base atoms, then compute the base checks + * for those tips against all refs. + * + * If this is not called, then any is-base atoms will be blank. + */ +void filter_is_base(struct repository *r, + struct ref_format *format, + struct ref_array *array); + void ref_filter_init(struct ref_filter *filter); void ref_filter_clear(struct ref_filter *filter); +void ref_format_init(struct ref_format *format); +void ref_format_clear(struct ref_format *format); + #endif /* REF_FILTER_H */ @@ -210,7 +210,7 @@ static void mark_reachable(struct expire_reflog_policy_cb *cb) cb->mark_list = leftover; } -static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid) +static int is_unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid) { /* * We may or may not have the commit yet - if not, look it @@ -265,7 +265,7 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, return 1; case UE_NORMAL: case UE_HEAD: - if (unreachable(cb, old_commit, ooid) || unreachable(cb, new_commit, noid)) + if (is_unreachable(cb, old_commit, ooid) || is_unreachable(cb, new_commit, noid)) return 1; break; } @@ -300,6 +300,7 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid, } static int push_tip_to_list(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags, void *cb_data) { @@ -332,7 +333,8 @@ void reflog_expiry_prepare(const char *refname, if (!cb->cmd.expire_unreachable || is_head(refname)) { cb->unreachable_expire_kind = UE_HEAD; } else { - commit = lookup_commit(the_repository, oid); + commit = lookup_commit_reference_gently(the_repository, + oid, 1); if (commit && is_null_oid(&commit->object.oid)) commit = NULL; cb->unreachable_expire_kind = commit ? UE_NORMAL : UE_ALWAYS; @@ -24,7 +24,7 @@ #include "submodule.h" #include "worktree.h" #include "strvec.h" -#include "repository.h" +#include "repo-settings.h" #include "setup.h" #include "sigchain.h" #include "date.h" @@ -318,6 +318,12 @@ int check_refname_format(const char *refname, int flags) return check_or_sanitize_refname(refname, flags, NULL); } +int refs_fsck(struct ref_store *refs, struct fsck_options *o, + struct worktree *wt) +{ + return refs->be->fsck(refs, o, wt); +} + void sanitize_refname_component(const char *refname, struct strbuf *out) { if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out)) @@ -414,7 +420,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname) NULL, NULL); } -static int for_each_filter_refs(const char *refname, +static int for_each_filter_refs(const char *refname, const char *referent, const struct object_id *oid, int flags, void *data) { @@ -424,7 +430,7 @@ static int for_each_filter_refs(const char *refname, return 0; if (filter->prefix) skip_prefix(refname, filter->prefix, &refname); - return filter->fn(refname, oid, flags, filter->cb_data); + return filter->fn(refname, referent, oid, flags, filter->cb_data); } struct warn_if_dangling_data { @@ -435,7 +441,7 @@ struct warn_if_dangling_data { const char *msg_fmt; }; -static int warn_if_dangling_symref(const char *refname, +static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flags, void *cb_data) { @@ -506,7 +512,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da strbuf_addf(&buf, "%sHEAD", get_git_namespace()); if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag)) - ret = fn(buf.buf, &oid, flag, cb_data); + ret = fn(buf.buf, NULL, &oid, flag, cb_data); strbuf_release(&buf); return ret; @@ -692,6 +698,53 @@ static char *substitute_branch_name(struct repository *r, return NULL; } +void copy_branchname(struct strbuf *sb, const char *name, unsigned allowed) +{ + int len = strlen(name); + struct interpret_branch_name_options options = { + .allowed = allowed + }; + int used = repo_interpret_branch_name(the_repository, name, len, sb, + &options); + + if (used < 0) + used = 0; + strbuf_add(sb, name + used, len - used); +} + +int check_branch_ref(struct strbuf *sb, const char *name) +{ + if (startup_info->have_repository) + copy_branchname(sb, name, INTERPRET_BRANCH_LOCAL); + else + strbuf_addstr(sb, name); + + /* + * This splice must be done even if we end up rejecting the + * name; builtin/branch.c::copy_or_rename_branch() still wants + * to see what the name expanded to so that "branch -m" can be + * used as a tool to correct earlier mistakes. + */ + strbuf_splice(sb, 0, 0, "refs/heads/", 11); + + if (*name == '-' || + !strcmp(sb->buf, "refs/heads/HEAD")) + return -1; + + return check_refname_format(sb->buf, 0); +} + +int check_tag_ref(struct strbuf *sb, const char *name) +{ + if (name[0] == '-' || !strcmp(name, "HEAD")) + return -1; + + strbuf_reset(sb); + strbuf_addf(sb, "refs/tags/%s", name); + + return check_refname_format(sb->buf, 0); +} + int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref, int nonfatal_dangling_mark) { @@ -725,7 +778,7 @@ int expand_ref(struct repository *repo, const char *str, int len, if (r) { if (!refs_found++) *ref = xstrdup(r); - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(repo)) break; } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) { warning(_("ignoring dangling symref %s"), fullref.buf); @@ -770,7 +823,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len, if (oid) oidcpy(oid, &hash); } - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(r)) break; } strbuf_release(&path); @@ -913,7 +966,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg, struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction || ref_transaction_delete(transaction, refname, old_oid, NULL, flags, msg, &err) || @@ -953,7 +1006,8 @@ static char *normalize_reflog_message(const char *msg) return strbuf_detach(&sb, NULL); } -int should_autocreate_reflog(const char *refname) +int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, + const char *refname) { switch (log_all_ref_updates) { case LOG_REFS_ALWAYS: @@ -1110,6 +1164,7 @@ int read_ref_at(struct ref_store *refs, const char *refname, } struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, + unsigned int flags, struct strbuf *err) { struct ref_transaction *tr; @@ -1117,6 +1172,7 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, CALLOC_ARRAY(tr, 1); tr->ref_store = refs; + tr->flags = flags; return tr; } @@ -1180,8 +1236,9 @@ struct ref_update *ref_transaction_add_update( oidcpy(&update->new_oid, new_oid); if ((flags & REF_HAVE_OLD) && old_oid) oidcpy(&update->old_oid, old_oid); + if (!(flags & REF_SKIP_CREATE_REFLOG)) + update->msg = normalize_reflog_message(msg); - update->msg = normalize_reflog_message(msg); return update; } @@ -1303,7 +1360,7 @@ int refs_update_ref(struct ref_store *refs, const char *msg, struct strbuf err = STRBUF_INIT; int ret = 0; - t = ref_store_transaction_begin(refs, &err); + t = ref_store_transaction_begin(refs, 0, &err); if (!t || ref_transaction_update(t, refname, new_oid, old_oid, NULL, NULL, flags, msg, &err) || @@ -1512,6 +1569,19 @@ const char **hidden_refs_to_excludes(const struct strvec *hide_refs) return hide_refs->v; } +const char **get_namespaced_exclude_patterns(const char **exclude_patterns, + const char *namespace, + struct strvec *out) +{ + if (!namespace || !*namespace || !exclude_patterns || !*exclude_patterns) + return exclude_patterns; + + for (size_t i = 0; exclude_patterns[i]; i++) + strvec_pushf(out, "%s%s", namespace, exclude_patterns[i]); + + return out->v; +} + const char *find_descendant_ref(const char *dirname, const struct string_list *extras, const struct string_list *skip) @@ -1547,7 +1617,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING, &oid, &flag)) - return fn("HEAD", &oid, flag, cb_data); + return fn("HEAD", NULL, &oid, flag, cb_data); return 0; } @@ -1629,11 +1699,19 @@ int refs_for_each_namespaced_ref(struct ref_store *refs, const char **exclude_patterns, each_ref_fn fn, void *cb_data) { - struct strbuf buf = STRBUF_INIT; + struct strvec namespaced_exclude_patterns = STRVEC_INIT; + struct strbuf prefix = STRBUF_INIT; int ret; - strbuf_addf(&buf, "%srefs/", get_git_namespace()); - ret = do_for_each_ref(refs, buf.buf, exclude_patterns, fn, 0, 0, cb_data); - strbuf_release(&buf); + + exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns, + get_git_namespace(), + &namespaced_exclude_patterns); + + strbuf_addf(&prefix, "%srefs/", get_git_namespace()); + ret = do_for_each_ref(refs, prefix.buf, exclude_patterns, fn, 0, 0, cb_data); + + strvec_clear(&namespaced_exclude_patterns); + strbuf_release(&prefix); return ret; } @@ -1714,6 +1792,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, const char **exclude_patterns, each_ref_fn fn, void *cb_data) { + struct strvec namespaced_exclude_patterns = STRVEC_INIT; struct string_list prefixes = STRING_LIST_INIT_DUP; struct string_list_item *prefix; struct strbuf buf = STRBUF_INIT; @@ -1725,6 +1804,10 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, strbuf_addstr(&buf, namespace); namespace_len = buf.len; + exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns, + namespace, + &namespaced_exclude_patterns); + for_each_string_list_item(prefix, &prefixes) { strbuf_addstr(&buf, prefix->string); ret = refs_for_each_fullref_in(ref_store, buf.buf, @@ -1734,6 +1817,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, strbuf_setlen(&buf, namespace_len); } + strvec_clear(&namespaced_exclude_patterns); string_list_clear(&prefixes, 0); strbuf_release(&buf); return ret; @@ -1754,8 +1838,8 @@ static int refs_read_special_head(struct ref_store *ref_store, goto done; } - result = parse_loose_ref_contents(content.buf, oid, referent, type, - failure_errno); + result = parse_loose_ref_contents(ref_store->repo->hash_algo, content.buf, + oid, referent, type, NULL, failure_errno); done: strbuf_release(&full_path); @@ -1838,7 +1922,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, failure_errno != ENOTDIR) return NULL; - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); if (*flags & REF_BAD_NAME) *flags |= REF_ISBROKEN; return refname; @@ -1848,7 +1932,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, if (!(read_flags & REF_ISSYMREF)) { if (*flags & REF_BAD_NAME) { - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); *flags |= REF_ISBROKEN; } return refname; @@ -1856,7 +1940,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, refname = sb_refname.buf; if (resolve_flags & RESOLVE_REF_NO_RECURSE) { - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); return refname; } if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { @@ -2011,7 +2095,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, free(subrepo); goto done; } - refs = ref_store_init(subrepo, the_repository->ref_storage_format, + refs = ref_store_init(subrepo, subrepo->ref_storage_format, submodule_sb.buf, REF_STORE_READ | REF_STORE_ODB); register_ref_store_map(&repo->submodule_ref_stores, "submodule", @@ -2045,7 +2129,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) common_path.buf, REF_STORE_ALL_CAPS); strbuf_release(&common_path); } else { - refs = ref_store_init(wt->repo, the_repository->ref_storage_format, + refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, wt->repo->commondir, REF_STORE_ALL_CAPS); } @@ -2087,7 +2171,7 @@ int refs_update_symref(struct ref_store *refs, const char *ref, struct strbuf err = STRBUF_INIT; int ret = 0; - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction || ref_transaction_update(transaction, ref, NULL, NULL, target, NULL, REF_NO_DEREF, @@ -2134,7 +2218,7 @@ static int run_transaction_hook(struct ref_transaction *transaction, const char *hook; int ret = 0, i; - hook = find_hook("reference-transaction"); + hook = find_hook(transaction->ref_store->repo, "reference-transaction"); if (!hook) return ret; @@ -2152,6 +2236,9 @@ static int run_transaction_hook(struct ref_transaction *transaction, for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; + if (update->flags & REF_LOG_ONLY) + continue; + strbuf_reset(&buf); if (!(update->flags & REF_HAVE_OLD)) @@ -2280,7 +2367,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, } ret = refs->be->transaction_finish(refs, transaction, err); - if (!ret) + if (!ret && !(transaction->flags & REF_TRANSACTION_FLAG_INITIAL)) run_transaction_hook(transaction, "committed"); return ret; } @@ -2289,6 +2376,7 @@ int refs_verify_refname_available(struct ref_store *refs, const char *refname, const struct string_list *extras, const struct string_list *skip, + unsigned int initial_transaction, struct strbuf *err) { const char *slash; @@ -2297,8 +2385,6 @@ int refs_verify_refname_available(struct ref_store *refs, struct strbuf referent = STRBUF_INIT; struct object_id oid; unsigned int type; - struct ref_iterator *iter; - int ok; int ret = -1; /* @@ -2328,7 +2414,8 @@ int refs_verify_refname_available(struct ref_store *refs, if (skip && string_list_has_string(skip, dirname.buf)) continue; - if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + if (!initial_transaction && + !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type, &ignore_errno)) { strbuf_addf(err, _("'%s' exists; cannot create '%s'"), dirname.buf, refname); @@ -2353,21 +2440,26 @@ int refs_verify_refname_available(struct ref_store *refs, strbuf_addstr(&dirname, refname + dirname.len); strbuf_addch(&dirname, '/'); - iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, - DO_FOR_EACH_INCLUDE_BROKEN); - while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - if (skip && - string_list_has_string(skip, iter->refname)) - continue; + if (!initial_transaction) { + struct ref_iterator *iter; + int ok; - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - iter->refname, refname); - ref_iterator_abort(iter); - goto cleanup; - } + iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, + DO_FOR_EACH_INCLUDE_BROKEN); + while ((ok = ref_iterator_advance(iter)) == ITER_OK) { + if (skip && + string_list_has_string(skip, iter->refname)) + continue; - if (ok != ITER_DONE) - BUG("error while iterating over references"); + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + iter->refname, refname); + ref_iterator_abort(iter); + goto cleanup; + } + + if (ok != ITER_DONE) + BUG("error while iterating over references"); + } extra_refname = find_descendant_ref(dirname.buf, extras, skip); if (extra_refname) @@ -2388,8 +2480,9 @@ struct do_for_each_reflog_help { }; static int do_for_each_reflog_helper(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, - int flags, + int flags UNUSED, void *cb_data) { struct do_for_each_reflog_help *hp = cb_data; @@ -2450,14 +2543,6 @@ int refs_reflog_expire(struct ref_store *refs, cleanup_fn, policy_cb_data); } -int initial_ref_transaction_commit(struct ref_transaction *transaction, - struct strbuf *err) -{ - struct ref_store *refs = transaction->ref_store; - - return refs->be->initial_transaction_commit(refs, transaction, err); -} - void ref_transaction_for_each_queued_update(struct ref_transaction *transaction, ref_transaction_for_each_queued_update_fn cb, void *cb_data) @@ -2493,7 +2578,7 @@ int refs_delete_refs(struct ref_store *refs, const char *logmsg, * individual updates can't fail, so we can pack all of the * updates into a single transaction. */ - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction) { ret = error("%s", err.buf); goto out; @@ -2593,7 +2678,7 @@ struct migration_data { struct strbuf *errbuf; }; -static int migrate_one_ref(const char *refname, const struct object_id *oid, +static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags, void *cb_data) { struct migration_data *data = cb_data; @@ -2799,7 +2884,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - transaction = ref_store_transaction_begin(new_refs, errbuf); + transaction = ref_store_transaction_begin(new_refs, REF_TRANSACTION_FLAG_INITIAL, + errbuf); if (!transaction) goto done; @@ -2824,13 +2910,6 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - /* - * TODO: we might want to migrate to `initial_ref_transaction_commit()` - * here, which is more efficient for the files backend because it would - * write new refs into the packed-refs file directly. At this point, - * the files backend doesn't handle pseudo-refs and symrefs correctly - * though, so this requires some more work. - */ ret = ref_transaction_commit(transaction, errbuf); if (ret < 0) goto done; @@ -3,7 +3,9 @@ #include "commit.h" #include "repository.h" +#include "repo-settings.h" +struct fsck_options; struct object_id; struct ref_store; struct strbuf; @@ -15,7 +17,7 @@ enum ref_storage_format ref_storage_format_by_name(const char *name); const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format); /* - * Resolve a reference, recursively following symbolic refererences. + * Resolve a reference, recursively following symbolic references. * * Return the name of the non-symbolic reference that ultimately pointed * at the resolved object name. The return value, if not NULL, is a @@ -99,18 +101,22 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname, * both "foo" and with "foo/bar/baz" but not with "foo/bar" or * "foo/barbados". * + * If `initial_transaction` is truish, then all collision checks with + * preexisting refs are skipped. + * * extras and skip must be sorted. */ - int refs_verify_refname_available(struct ref_store *refs, const char *refname, const struct string_list *extras, const struct string_list *skip, + unsigned int initial_transaction, struct strbuf *err); int refs_ref_exists(struct ref_store *refs, const char *refname); -int should_autocreate_reflog(const char *refname); +int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, + const char *refname); int is_branch(const char *refname); @@ -178,6 +184,35 @@ int repo_dwim_log(struct repository *r, const char *str, int len, struct object_ char *repo_default_branch_name(struct repository *r, int quiet); /* + * Copy "name" to "sb", expanding any special @-marks as handled by + * repo_interpret_branch_name(). The result is a non-qualified branch name + * (so "foo" or "origin/master" instead of "refs/heads/foo" or + * "refs/remotes/origin/master"). + * + * Note that the resulting name may not be a syntactically valid refname. + * + * If "allowed" is non-zero, restrict the set of allowed expansions. See + * repo_interpret_branch_name() for details. + */ +void copy_branchname(struct strbuf *sb, const char *name, + unsigned allowed); + +/* + * Like copy_branchname() above, but confirm that the result is + * syntactically valid to be used as a local branch name in refs/heads/. + * + * The return value is "0" if the result is valid, and "-1" otherwise. + */ +int check_branch_ref(struct strbuf *sb, const char *name); + +/* + * Similar for a tag name in refs/tags/. + * + * The return value is "0" if the result is valid, and "-1" otherwise. + */ +int check_tag_ref(struct strbuf *sb, const char *name); + +/* * A ref_transaction represents a collection of reference updates that * should succeed or fail together. * @@ -211,11 +246,9 @@ char *repo_default_branch_name(struct repository *r, int quiet); * * Or * - * - Call `initial_ref_transaction_commit()` if the ref database is - * known to be empty and have no other writers (e.g. during - * clone). This is likely to be much faster than - * `ref_transaction_commit()`. `ref_transaction_prepare()` should - * *not* be called before `initial_ref_transaction_commit()`. + * - Call `ref_transaction_begin()` with REF_TRANSACTION_FLAG_INITIAL if the + * ref database is known to be empty and have no other writers (e.g. during + * clone). This is likely to be much faster than without the flag. * * - Then finally, call `ref_transaction_free()` to free the * `ref_transaction` data structure. @@ -231,7 +264,7 @@ char *repo_default_branch_name(struct repository *r, int quiet); * struct strbuf err = STRBUF_INIT; * int ret = 0; * - * transaction = ref_store_transaction_begin(refs, &err); + * transaction = ref_store_transaction_begin(refs, 0, &err); * if (!transaction || * ref_transaction_update(...) || * ref_transaction_create(...) || @@ -298,7 +331,7 @@ struct ref_transaction; * arguments is only guaranteed to be valid for the duration of a * single callback invocation. */ -typedef int each_ref_fn(const char *refname, +typedef int each_ref_fn(const char *refname, const char *referent, const struct object_id *oid, int flags, void *cb_data); /* @@ -487,7 +520,7 @@ int refs_delete_reflog(struct ref_store *refs, const char *refname); * from UTC. Its absolute value is formed by multiplying the hour * part by 100 and adding the minute part. For example, 1 hour ahead * of UTC, CET == "+0100", is represented as positive one hundred (not - * postiive sixty). + * positive sixty). * * The msg parameter is a single complete line; a reflog message given * to refs_delete_ref, refs_update_ref, etc. is returned to the @@ -542,6 +575,14 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat int check_refname_format(const char *refname, int flags); /* + * Check the reference database for consistency. Return 0 if refs and + * reflogs are consistent, and non-zero otherwise. The errors will be + * written to stderr. + */ +int refs_fsck(struct ref_store *refs, struct fsck_options *o, + struct worktree *wt); + +/* * Apply the rules from check_refname_format, but mutate the result until it * is acceptable, and place the result in "out". */ @@ -569,11 +610,27 @@ enum action_on_err { UPDATE_REFS_QUIET_ON_ERR }; +enum ref_transaction_flag { + /* + * The ref transaction is part of the initial creation of the ref store + * and can thus assume that the ref store is completely empty. This + * allows the backend to perform the transaction more efficiently by + * skipping certain checks. + * + * It is a bug to set this flag when there might be other processes + * accessing the repository or if there are existing references that + * might conflict with the ones being created. All old_oid values must + * either be absent or null_oid. + */ + REF_TRANSACTION_FLAG_INITIAL = (1 << 0), +}; + /* * Begin a reference transaction. The reference transaction must * be freed by calling ref_transaction_free(). */ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, + unsigned int flags, struct strbuf *err); /* @@ -788,20 +845,6 @@ int ref_transaction_abort(struct ref_transaction *transaction, struct strbuf *err); /* - * Like ref_transaction_commit(), but optimized for creating - * references when originally initializing a repository (e.g., by "git - * clone"). It writes the new references directly to packed-refs - * without locking the individual references. - * - * It is a bug to call this function when there might be other - * processes accessing the repository or if there are existing - * references that might conflict with the ones being created. All - * old_oid values must either be absent or null_oid. - */ -int initial_ref_transaction_commit(struct ref_transaction *transaction, - struct strbuf *err); - -/* * Execute the given callback function for each of the reference updates which * have been queued in the given transaction. `old_oid` and `new_oid` may be * `NULL` pointers depending on whether the update has these object IDs set or @@ -851,6 +894,15 @@ int ref_is_hidden(const char *, const char *, const struct strvec *); */ const char **hidden_refs_to_excludes(const struct strvec *hide_refs); +/* + * Prefix all exclude patterns with the namespace, if any. This is required + * because exclude patterns apply to the stripped reference name, not the full + * reference name with the namespace. + */ +const char **get_namespaced_exclude_patterns(const char **exclude_patterns, + const char *namespace, + struct strvec *out); + /* Is this a per-worktree ref living in the refs/ namespace? */ int is_per_worktree_ref(const char *refname); @@ -978,7 +1030,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt); /* * Some of the names specified by refs have special meaning to Git. - * Organize these namespaces in a comon 'ref_namespace' array for + * Organize these namespaces in a common 'ref_namespace' array for * reference from multiple places in the codebase. */ @@ -1086,211 +1138,4 @@ int repo_migrate_ref_storage_format(struct repository *repo, unsigned int flags, struct strbuf *err); -/* - * The following functions have been removed in Git v2.46 in favor of functions - * that receive a `ref_store` as parameter. The intent of this section is - * merely to help patch authors of in-flight series to have a reference what - * they should be migrating to. The section will be removed in Git v2.47. - */ -#if 0 -static char *resolve_refdup(const char *refname, int resolve_flags, - struct object_id *oid, int *flags) -{ - return refs_resolve_refdup(get_main_ref_store(the_repository), - refname, resolve_flags, - oid, flags); -} - -static int read_ref_full(const char *refname, int resolve_flags, - struct object_id *oid, int *flags) -{ - return refs_read_ref_full(get_main_ref_store(the_repository), refname, - resolve_flags, oid, flags); -} - -static int read_ref(const char *refname, struct object_id *oid) -{ - return refs_read_ref(get_main_ref_store(the_repository), refname, oid); -} - -static int ref_exists(const char *refname) -{ - return refs_ref_exists(get_main_ref_store(the_repository), refname); -} - -static int for_each_tag_ref(each_ref_fn fn, void *cb_data) -{ - return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data); -} - -static int for_each_branch_ref(each_ref_fn fn, void *cb_data) -{ - return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data); -} - -static int for_each_remote_ref(each_ref_fn fn, void *cb_data) -{ - return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data); -} - -static int head_ref_namespaced(each_ref_fn fn, void *cb_data) -{ - return refs_head_ref_namespaced(get_main_ref_store(the_repository), - fn, cb_data); -} - -static int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, - const char *prefix, void *cb_data) -{ - return refs_for_each_glob_ref_in(get_main_ref_store(the_repository), - fn, pattern, prefix, cb_data); -} - -static int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data) -{ - return refs_for_each_glob_ref(get_main_ref_store(the_repository), - fn, pattern, cb_data); -} - -static int delete_ref(const char *msg, const char *refname, - const struct object_id *old_oid, unsigned int flags) -{ - return refs_delete_ref(get_main_ref_store(the_repository), msg, refname, - old_oid, flags); -} - -static struct ref_transaction *ref_transaction_begin(struct strbuf *err) -{ - return ref_store_transaction_begin(get_main_ref_store(the_repository), err); -} - -static int update_ref(const char *msg, const char *refname, - const struct object_id *new_oid, - const struct object_id *old_oid, - unsigned int flags, enum action_on_err onerr) -{ - return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid, - old_oid, flags, onerr); -} - -static char *shorten_unambiguous_ref(const char *refname, int strict) -{ - return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), - refname, strict); -} - -static int head_ref(each_ref_fn fn, void *cb_data) -{ - return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data); -} - -static int for_each_ref(each_ref_fn fn, void *cb_data) -{ - return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data); -} - -static int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data) -{ - return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data); -} - -static int for_each_fullref_in(const char *prefix, - const char **exclude_patterns, - each_ref_fn fn, void *cb_data) -{ - return refs_for_each_fullref_in(get_main_ref_store(the_repository), - prefix, exclude_patterns, fn, cb_data); -} - -static int for_each_namespaced_ref(const char **exclude_patterns, - each_ref_fn fn, void *cb_data) -{ - return refs_for_each_namespaced_ref(get_main_ref_store(the_repository), - exclude_patterns, fn, cb_data); -} - -static int for_each_rawref(each_ref_fn fn, void *cb_data) -{ - return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data); -} - -static const char *resolve_ref_unsafe(const char *refname, int resolve_flags, - struct object_id *oid, int *flags) -{ - return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname, - resolve_flags, oid, flags); -} - -static int create_symref(const char *ref_target, const char *refs_heads_master, - const char *logmsg) -{ - return refs_create_symref(get_main_ref_store(the_repository), ref_target, - refs_heads_master, logmsg); -} - -static int for_each_reflog(each_reflog_fn fn, void *cb_data) -{ - return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data); -} - -static int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, - void *cb_data) -{ - return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository), - refname, fn, cb_data); -} - -static int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, - void *cb_data) -{ - return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname, - fn, cb_data); -} - -static int reflog_exists(const char *refname) -{ - return refs_reflog_exists(get_main_ref_store(the_repository), refname); -} - -static int safe_create_reflog(const char *refname, struct strbuf *err) -{ - return refs_create_reflog(get_main_ref_store(the_repository), refname, - err); -} - -static int delete_reflog(const char *refname) -{ - return refs_delete_reflog(get_main_ref_store(the_repository), refname); -} - -static int reflog_expire(const char *refname, - unsigned int flags, - reflog_expiry_prepare_fn prepare_fn, - reflog_expiry_should_prune_fn should_prune_fn, - reflog_expiry_cleanup_fn cleanup_fn, - void *policy_cb_data) -{ - return refs_reflog_expire(get_main_ref_store(the_repository), - refname, flags, - prepare_fn, should_prune_fn, - cleanup_fn, policy_cb_data); -} - -static int delete_refs(const char *msg, struct string_list *refnames, - unsigned int flags) -{ - return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags); -} - -static int rename_ref(const char *oldref, const char *newref, const char *logmsg) -{ - return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); -} - -static int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg) -{ - return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); -} -#endif - #endif /* REFS_H */ diff --git a/refs/debug.c b/refs/debug.c index 547d9245b9..a893ae0c90 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -118,18 +118,6 @@ static int debug_transaction_abort(struct ref_store *refs, return res; } -static int debug_initial_transaction_commit(struct ref_store *refs, - struct ref_transaction *transaction, - struct strbuf *err) -{ - struct debug_ref_store *drefs = (struct debug_ref_store *)refs; - int res; - transaction->ref_store = drefs->refs; - res = drefs->refs->be->initial_transaction_commit(drefs->refs, - transaction, err); - return res; -} - static int debug_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *opts) { struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store; @@ -419,6 +407,16 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname, return res; } +static int debug_fsck(struct ref_store *ref_store, + struct fsck_options *o, + struct worktree *wt) +{ + struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store; + int res = drefs->refs->be->fsck(drefs->refs, o, wt); + trace_printf_key(&trace_refs, "fsck: %d\n", res); + return res; +} + struct ref_storage_be refs_be_debug = { .name = "debug", .init = NULL, @@ -434,7 +432,6 @@ struct ref_storage_be refs_be_debug = { .transaction_prepare = debug_transaction_prepare, .transaction_finish = debug_transaction_finish, .transaction_abort = debug_transaction_abort, - .initial_transaction_commit = debug_initial_transaction_commit, .pack_refs = debug_pack_refs, .rename_ref = debug_rename_ref, @@ -451,4 +448,6 @@ struct ref_storage_be refs_be_debug = { .create_reflog = debug_create_reflog, .delete_reflog = debug_delete_reflog, .reflog_expire = debug_reflog_expire, + + .fsck = debug_fsck, }; diff --git a/refs/files-backend.c b/refs/files-backend.c index aa52d9be7c..64f51f0da9 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1,12 +1,16 @@ #define USE_THE_REPOSITORY_VARIABLE #include "../git-compat-util.h" +#include "../abspath.h" +#include "../config.h" #include "../copy.h" #include "../environment.h" #include "../gettext.h" #include "../hash.h" #include "../hex.h" +#include "../fsck.h" #include "../refs.h" +#include "../repo-settings.h" #include "refs-internal.h" #include "ref-cache.h" #include "packed-backend.h" @@ -20,6 +24,7 @@ #include "../dir.h" #include "../chdir-notify.h" #include "../setup.h" +#include "../worktree.h" #include "../wrapper.h" #include "../write-or-die.h" #include "../revision.h" @@ -73,6 +78,8 @@ struct files_ref_store { unsigned int store_flags; char *gitcommondir; + enum log_refs_config log_all_ref_updates; + int prefer_symlink_refs; struct ref_cache *loose; @@ -105,6 +112,8 @@ static struct ref_store *files_ref_store_init(struct repository *repo, refs->gitcommondir = strbuf_detach(&sb, NULL); refs->packed_ref_store = packed_ref_store_init(repo, refs->gitcommondir, flags); + refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); + repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs); chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir); chdir_notify_reparent("files-backend $GIT_COMMONDIR", @@ -157,6 +166,7 @@ static void files_ref_store_release(struct ref_store *ref_store) free_ref_cache(refs->loose); free(refs->gitcommondir); ref_store_release(refs->packed_ref_store); + free(refs->packed_ref_store); } static void files_reflog_path(struct files_ref_store *refs, @@ -245,10 +255,13 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs, { struct object_id oid; int flag; + const char *referent = refs_resolve_ref_unsafe(&refs->base, + refname, + RESOLVE_REF_READING, + &oid, &flag); - if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING, - &oid, &flag)) { - oidclr(&oid, the_repository->hash_algo); + if (!referent) { + oidclr(&oid, refs->base.repo->hash_algo); flag |= REF_ISBROKEN; } else if (is_null_oid(&oid)) { /* @@ -265,10 +278,14 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs, if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(refname)) die("loose refname is dangerous: %s", refname); - oidclr(&oid, the_repository->hash_algo); + oidclr(&oid, refs->base.repo->hash_algo); flag |= REF_BAD_NAME | REF_ISBROKEN; } - add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag)); + + if (!(flag & REF_ISSYMREF)) + referent = NULL; + + add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag)); } /* @@ -552,7 +569,8 @@ stat_ref: strbuf_rtrim(&sb_contents); buf = sb_contents.buf; - ret = parse_loose_ref_contents(buf, oid, referent, type, &myerr); + ret = parse_loose_ref_contents(ref_store->repo->hash_algo, buf, + oid, referent, type, NULL, &myerr); out: if (ret && !myerr) @@ -586,9 +604,10 @@ static int files_read_symbolic_ref(struct ref_store *ref_store, const char *refn return !(type & REF_ISSYMREF); } -int parse_loose_ref_contents(const char *buf, struct object_id *oid, +int parse_loose_ref_contents(const struct git_hash_algo *algop, + const char *buf, struct object_id *oid, struct strbuf *referent, unsigned int *type, - int *failure_errno) + const char **trailing, int *failure_errno) { const char *p; if (skip_prefix(buf, "ref:", &buf)) { @@ -604,12 +623,16 @@ int parse_loose_ref_contents(const char *buf, struct object_id *oid, /* * FETCH_HEAD has additional data after the sha. */ - if (parse_oid_hex(buf, oid, &p) || + if (parse_oid_hex_algop(buf, oid, &p, algop) || (*p != '\0' && !isspace(*p))) { *type |= REF_ISBROKEN; *failure_errno = EINVAL; return -1; } + + if (trailing) + *trailing = p; + return 0; } @@ -689,7 +712,7 @@ retry: * reason to expect this error to be transitory. */ if (refs_verify_refname_available(&refs->base, refname, - extras, NULL, err)) { + extras, NULL, 0, err)) { if (mustexist) { /* * To the user the relevant error is @@ -796,7 +819,7 @@ retry: REMOVE_DIR_EMPTY_ONLY)) { if (refs_verify_refname_available( &refs->base, refname, - extras, NULL, err)) { + extras, NULL, 0, err)) { /* * The error message set by * verify_refname_available() is OK. @@ -833,7 +856,7 @@ retry: */ if (refs_verify_refname_available( refs->packed_ref_store, refname, - extras, NULL, err)) { + extras, NULL, 0, err)) { ret = TRANSACTION_NAME_CONFLICT; goto error_return; } @@ -886,6 +909,8 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator) iter->base.refname = iter->iter0->refname; iter->base.oid = iter->iter0->oid; iter->base.flags = iter->iter0->flags; + iter->base.referent = iter->iter0->referent; + return ITER_OK; } @@ -1140,7 +1165,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, */ if (is_null_oid(&lock->old_oid) && refs_verify_refname_available(refs->packed_ref_store, refname, - NULL, NULL, err)) + NULL, NULL, 0, err)) goto error_return; lock->ref_name = xstrdup(refname); @@ -1152,7 +1177,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0, &lock->old_oid, NULL)) - oidclr(&lock->old_oid, the_repository->hash_algo); + oidclr(&lock->old_oid, refs->base.repo->hash_algo); goto out; error_return: @@ -1233,7 +1258,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r) if (check_refname_format(r->name, 0)) return; - transaction = ref_store_transaction_begin(&refs->base, &err); + transaction = ref_store_transaction_begin(&refs->base, 0, &err); if (!transaction) goto cleanup; ref_transaction_add_update( @@ -1300,6 +1325,68 @@ static int should_pack_ref(struct files_ref_store *refs, return 0; } +static int should_pack_refs(struct files_ref_store *refs, + struct pack_refs_opts *opts) +{ + struct ref_iterator *iter; + size_t packed_size; + size_t refcount = 0; + size_t limit; + int ret; + + if (!(opts->flags & PACK_REFS_AUTO)) + return 1; + + ret = packed_refs_size(refs->packed_ref_store, &packed_size); + if (ret < 0) + die("cannot determine packed-refs size"); + + /* + * Packing loose references into the packed-refs file scales with the + * number of references we're about to write. We thus decide whether we + * repack refs by weighing the current size of the packed-refs file + * against the number of loose references. This is done such that we do + * not repack too often on repositories with a huge number of + * references, where we can expect a lot of churn in the number of + * references. + * + * As a heuristic, we repack if the number of loose references in the + * repository exceeds `log2(nr_packed_refs) * 5`, where we estimate + * `nr_packed_refs = packed_size / 100`, which scales as following: + * + * - 1kB ~ 10 packed refs: 16 refs + * - 10kB ~ 100 packed refs: 33 refs + * - 100kB ~ 1k packed refs: 49 refs + * - 1MB ~ 10k packed refs: 66 refs + * - 10MB ~ 100k packed refs: 82 refs + * - 100MB ~ 1m packed refs: 99 refs + * + * We thus allow roughly 16 additional loose refs per factor of ten of + * packed refs. This heuristic may be tweaked in the future, but should + * serve as a sufficiently good first iteration. + */ + limit = log2u(packed_size / 100) * 5; + if (limit < 16) + limit = 16; + + iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL, + refs->base.repo, 0); + while ((ret = ref_iterator_advance(iter)) == ITER_OK) { + if (should_pack_ref(refs, iter->refname, iter->oid, + iter->flags, opts)) + refcount++; + if (refcount >= limit) { + ref_iterator_abort(iter); + return 1; + } + } + + if (ret != ITER_DONE) + die("error while iterating over references"); + + return 0; +} + static int files_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *opts) { @@ -1312,7 +1399,11 @@ static int files_pack_refs(struct ref_store *ref_store, struct strbuf err = STRBUF_INIT; struct ref_transaction *transaction; - transaction = ref_store_transaction_begin(refs->packed_ref_store, &err); + if (!should_pack_refs(refs, opts)) + return 0; + + transaction = ref_store_transaction_begin(refs->packed_ref_store, + 0, &err); if (!transaction) return -1; @@ -1430,6 +1521,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, + int flags, struct strbuf *err); /* @@ -1452,7 +1544,7 @@ static int refs_rename_ref_available(struct ref_store *refs, string_list_insert(&skip, old_refname); ok = !refs_verify_refname_available(refs, new_refname, - NULL, &skip, &err); + NULL, &skip, 0, &err); if (!ok) error("%s", err.buf); @@ -1573,7 +1665,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, oidcpy(&lock->old_oid, &orig_oid); if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || - commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) { + commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) { error("unable to write current sha1 into %s: %s", newrefname, err.buf); strbuf_release(&err); goto rollback; @@ -1590,14 +1682,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, goto rollbacklog; } - flag = log_all_ref_updates; - log_all_ref_updates = LOG_REFS_NONE; if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) || - commit_ref_update(refs, lock, &orig_oid, NULL, &err)) { + commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) { error("unable to write current sha1 into %s: %s", oldrefname, err.buf); strbuf_release(&err); } - log_all_ref_updates = flag; rollbacklog: if (logmoved && rename(sb_newref.buf, sb_oldref.buf)) @@ -1692,13 +1781,17 @@ static int log_ref_setup(struct files_ref_store *refs, const char *refname, int force_create, int *logfd, struct strbuf *err) { + enum log_refs_config log_refs_cfg = refs->log_all_ref_updates; struct strbuf logfile_sb = STRBUF_INIT; char *logfile; + if (log_refs_cfg == LOG_REFS_UNSET) + log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; + files_reflog_path(refs, &logfile_sb, refname); logfile = strbuf_detach(&logfile_sb, NULL); - if (force_create || should_autocreate_reflog(refname)) { + if (force_create || should_autocreate_reflog(log_refs_cfg, refname)) { if (raceproof_create_file(logfile, open_or_create_logfile, logfd)) { if (errno == ENOENT) strbuf_addf(err, "unable to create directory for '%s': " @@ -1787,9 +1880,6 @@ static int files_log_ref_write(struct files_ref_store *refs, if (flags & REF_SKIP_CREATE_REFLOG) return 0; - if (log_all_ref_updates == LOG_REFS_UNSET) - log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; - result = log_ref_setup(refs, refname, flags & REF_FORCE_CREATE_REFLOG, &logfd, err); @@ -1878,6 +1968,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, + int flags, struct strbuf *err) { files_assert_main_repository(refs, "commit_ref_update"); @@ -1885,7 +1976,7 @@ static int commit_ref_update(struct files_ref_store *refs, clear_loose_ref_cache(refs); if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid, oid, - logmsg, 0, err)) { + logmsg, flags, err)) { char *old_msg = strbuf_detach(err, NULL); strbuf_addf(err, "cannot update the ref '%s': %s", lock->ref_name, old_msg); @@ -1918,7 +2009,7 @@ static int commit_ref_update(struct files_ref_store *refs, struct strbuf log_err = STRBUF_INIT; if (files_log_ref_write(refs, "HEAD", &lock->old_oid, oid, - logmsg, 0, &log_err)) { + logmsg, flags, &log_err)) { error("%s", log_err.buf); strbuf_release(&log_err); } @@ -1935,10 +2026,13 @@ static int commit_ref_update(struct files_ref_store *refs, return 0; } +#ifdef NO_SYMLINK_HEAD +#define create_ref_symlink(a, b) (-1) +#else static int create_ref_symlink(struct ref_lock *lock, const char *target) { int ret = -1; -#ifndef NO_SYMLINK_HEAD + char *ref_path = get_locked_file_path(&lock->lk); unlink(ref_path); ret = symlink(target, ref_path); @@ -1946,13 +2040,12 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target) if (ret) fprintf(stderr, "no symlink - falling back to symbolic ref\n"); -#endif return ret; } +#endif -static int create_symref_lock(struct files_ref_store *refs, - struct ref_lock *lock, const char *refname, - const char *target, struct strbuf *err) +static int create_symref_lock(struct ref_lock *lock, const char *target, + struct strbuf *err) { if (!fdopen_lock_file(&lock->lk, "w")) { strbuf_addf(err, "unable to fdopen %s: %s", @@ -1998,7 +2091,8 @@ static int files_delete_reflog(struct ref_store *ref_store, return ret; } -static int show_one_reflog_ent(struct strbuf *sb, each_reflog_ent_fn fn, void *cb_data) +static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb, + each_reflog_ent_fn fn, void *cb_data) { struct object_id ooid, noid; char *email_end, *message; @@ -2008,8 +2102,8 @@ static int show_one_reflog_ent(struct strbuf *sb, each_reflog_ent_fn fn, void *c /* old SP new SP name <email> SP time TAB msg LF */ if (!sb->len || sb->buf[sb->len - 1] != '\n' || - parse_oid_hex(p, &ooid, &p) || *p++ != ' ' || - parse_oid_hex(p, &noid, &p) || *p++ != ' ' || + parse_oid_hex_algop(p, &ooid, &p, refs->base.repo->hash_algo) || *p++ != ' ' || + parse_oid_hex_algop(p, &noid, &p, refs->base.repo->hash_algo) || *p++ != ' ' || !(email_end = strchr(p, '>')) || email_end[1] != ' ' || !(timestamp = parse_timestamp(email_end + 2, &message, 10)) || @@ -2108,7 +2202,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1)); scanp = bp; endp = bp + 1; - ret = show_one_reflog_ent(&sb, fn, cb_data); + ret = show_one_reflog_ent(refs, &sb, fn, cb_data); strbuf_reset(&sb); if (ret) break; @@ -2120,7 +2214,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store, * Process it, and we can end the loop. */ strbuf_splice(&sb, 0, 0, buf, endp - buf); - ret = show_one_reflog_ent(&sb, fn, cb_data); + ret = show_one_reflog_ent(refs, &sb, fn, cb_data); strbuf_reset(&sb); break; } @@ -2170,7 +2264,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, return -1; while (!ret && !strbuf_getwholeline(&sb, logfp, '\n')) - ret = show_one_reflog_ent(&sb, fn, cb_data); + ret = show_one_reflog_ent(refs, &sb, fn, cb_data); fclose(logfp); strbuf_release(&sb); return ret; @@ -2567,8 +2661,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, } if (update->new_target && !(update->flags & REF_LOG_ONLY)) { - if (create_symref_lock(refs, lock, update->refname, - update->new_target, err)) { + if (create_symref_lock(lock, update->new_target, err)) { ret = TRANSACTION_GENERIC_ERROR; goto out; } @@ -2694,6 +2787,8 @@ static int files_transaction_prepare(struct ref_store *ref_store, assert(err); + if (transaction->flags & REF_TRANSACTION_FLAG_INITIAL) + goto cleanup; if (!transaction->nr) goto cleanup; @@ -2781,7 +2876,8 @@ static int files_transaction_prepare(struct ref_store *ref_store, */ if (!packed_transaction) { packed_transaction = ref_store_transaction_begin( - refs->packed_ref_store, err); + refs->packed_ref_store, + transaction->flags, err); if (!packed_transaction) { ret = TRANSACTION_GENERIC_ERROR; goto cleanup; @@ -2887,6 +2983,127 @@ static int parse_and_write_reflog(struct files_ref_store *refs, return 0; } +static int ref_present(const char *refname, const char *referent UNUSED, + const struct object_id *oid UNUSED, + int flags UNUSED, + void *cb_data) +{ + struct string_list *affected_refnames = cb_data; + + return string_list_has_string(affected_refnames, refname); +} + +static int files_transaction_finish_initial(struct files_ref_store *refs, + struct ref_transaction *transaction, + struct strbuf *err) +{ + size_t i; + int ret = 0; + struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct ref_transaction *packed_transaction = NULL; + struct ref_transaction *loose_transaction = NULL; + + assert(err); + + if (transaction->state != REF_TRANSACTION_PREPARED) + BUG("commit called for transaction that is not prepared"); + + /* Fail if a refname appears more than once in the transaction: */ + for (i = 0; i < transaction->nr; i++) + string_list_append(&affected_refnames, + transaction->updates[i]->refname); + string_list_sort(&affected_refnames); + if (ref_update_reject_duplicates(&affected_refnames, err)) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + + /* + * It's really undefined to call this function in an active + * repository or when there are existing references: we are + * only locking and changing packed-refs, so (1) any + * simultaneous processes might try to change a reference at + * the same time we do, and (2) any existing loose versions of + * the references that we are setting would have precedence + * over our values. But some remote helpers create the remote + * "HEAD" and "master" branches before calling this function, + * so here we really only check that none of the references + * that we are creating already exists. + */ + if (refs_for_each_rawref(&refs->base, ref_present, + &affected_refnames)) + BUG("initial ref transaction called with existing refs"); + + packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, + transaction->flags, err); + if (!packed_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + + for (i = 0; i < transaction->nr; i++) { + struct ref_update *update = transaction->updates[i]; + + if ((update->flags & REF_HAVE_OLD) && + !is_null_oid(&update->old_oid)) + BUG("initial ref transaction with old_sha1 set"); + + if (refs_verify_refname_available(&refs->base, update->refname, + &affected_refnames, NULL, 1, err)) { + ret = TRANSACTION_NAME_CONFLICT; + goto cleanup; + } + + /* + * packed-refs don't support symbolic refs and root refs, so we + * have to queue these references via the loose transaction. + */ + if (update->new_target || is_root_ref(update->refname)) { + if (!loose_transaction) { + loose_transaction = ref_store_transaction_begin(&refs->base, 0, err); + if (!loose_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + } + + ref_transaction_add_update(loose_transaction, update->refname, + update->flags & ~REF_HAVE_OLD, + update->new_target ? NULL : &update->new_oid, NULL, + update->new_target, NULL, NULL); + } else { + ref_transaction_add_update(packed_transaction, update->refname, + update->flags & ~REF_HAVE_OLD, + &update->new_oid, &update->old_oid, + NULL, NULL, NULL); + } + } + + if (packed_refs_lock(refs->packed_ref_store, 0, err) || + ref_transaction_commit(packed_transaction, err)) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + packed_refs_unlock(refs->packed_ref_store); + + if (loose_transaction) { + if (ref_transaction_prepare(loose_transaction, err) || + ref_transaction_commit(loose_transaction, err)) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + } + +cleanup: + if (loose_transaction) + ref_transaction_free(loose_transaction); + if (packed_transaction) + ref_transaction_free(packed_transaction); + transaction->state = REF_TRANSACTION_CLOSED; + string_list_clear(&affected_refnames, 0); + return ret; +} + static int files_transaction_finish(struct ref_store *ref_store, struct ref_transaction *transaction, struct strbuf *err) @@ -2902,6 +3119,8 @@ static int files_transaction_finish(struct ref_store *ref_store, assert(err); + if (transaction->flags & REF_TRANSACTION_FLAG_INITIAL) + return files_transaction_finish_initial(refs, transaction, err); if (!transaction->nr) { transaction->state = REF_TRANSACTION_CLOSED; return 0; @@ -2927,7 +3146,7 @@ static int files_transaction_finish(struct ref_store *ref_store, * We try creating a symlink, if that succeeds we continue to the * next update. If not, we try and create a regular symref. */ - if (update->new_target && prefer_symlink_refs) + if (update->new_target && refs->prefer_symlink_refs) if (!create_ref_symlink(lock, update->new_target)) continue; @@ -3035,106 +3254,6 @@ static int files_transaction_abort(struct ref_store *ref_store, return 0; } -static int ref_present(const char *refname, - const struct object_id *oid UNUSED, - int flags UNUSED, - void *cb_data) -{ - struct string_list *affected_refnames = cb_data; - - return string_list_has_string(affected_refnames, refname); -} - -static int files_initial_transaction_commit(struct ref_store *ref_store, - struct ref_transaction *transaction, - struct strbuf *err) -{ - struct files_ref_store *refs = - files_downcast(ref_store, REF_STORE_WRITE, - "initial_ref_transaction_commit"); - size_t i; - int ret = 0; - struct string_list affected_refnames = STRING_LIST_INIT_NODUP; - struct ref_transaction *packed_transaction = NULL; - - assert(err); - - if (transaction->state != REF_TRANSACTION_OPEN) - BUG("commit called for transaction that is not open"); - - /* Fail if a refname appears more than once in the transaction: */ - for (i = 0; i < transaction->nr; i++) - string_list_append(&affected_refnames, - transaction->updates[i]->refname); - string_list_sort(&affected_refnames); - if (ref_update_reject_duplicates(&affected_refnames, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto cleanup; - } - - /* - * It's really undefined to call this function in an active - * repository or when there are existing references: we are - * only locking and changing packed-refs, so (1) any - * simultaneous processes might try to change a reference at - * the same time we do, and (2) any existing loose versions of - * the references that we are setting would have precedence - * over our values. But some remote helpers create the remote - * "HEAD" and "master" branches before calling this function, - * so here we really only check that none of the references - * that we are creating already exists. - */ - if (refs_for_each_rawref(&refs->base, ref_present, - &affected_refnames)) - BUG("initial ref transaction called with existing refs"); - - packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, err); - if (!packed_transaction) { - ret = TRANSACTION_GENERIC_ERROR; - goto cleanup; - } - - for (i = 0; i < transaction->nr; i++) { - struct ref_update *update = transaction->updates[i]; - - if ((update->flags & REF_HAVE_OLD) && - !is_null_oid(&update->old_oid)) - BUG("initial ref transaction with old_sha1 set"); - if (refs_verify_refname_available(&refs->base, update->refname, - &affected_refnames, NULL, - err)) { - ret = TRANSACTION_NAME_CONFLICT; - goto cleanup; - } - - /* - * Add a reference creation for this reference to the - * packed-refs transaction: - */ - ref_transaction_add_update(packed_transaction, update->refname, - update->flags & ~REF_HAVE_OLD, - &update->new_oid, &update->old_oid, - NULL, NULL, NULL); - } - - if (packed_refs_lock(refs->packed_ref_store, 0, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto cleanup; - } - - if (initial_ref_transaction_commit(packed_transaction, err)) { - ret = TRANSACTION_GENERIC_ERROR; - } - - packed_refs_unlock(refs->packed_ref_store); -cleanup: - if (packed_transaction) - ref_transaction_free(packed_transaction); - transaction->state = REF_TRANSACTION_CLOSED; - string_list_clear(&affected_refnames, 0); - return ret; -} - struct expire_reflog_cb { reflog_expiry_should_prune_fn *should_prune_fn; void *policy_cb; @@ -3408,6 +3527,272 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store, return ret; } +/* + * For refs and reflogs, they share a unified interface when scanning + * the whole directory. This function is used as the callback for each + * regular file or symlink in the directory. + */ +typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store, + struct fsck_options *o, + const char *refname, + struct dir_iterator *iter); + +static int files_fsck_symref_target(struct fsck_options *o, + struct fsck_ref_report *report, + struct strbuf *referent, + unsigned int symbolic_link) +{ + int is_referent_root; + char orig_last_byte; + size_t orig_len; + int ret = 0; + + orig_len = referent->len; + orig_last_byte = referent->buf[orig_len - 1]; + if (!symbolic_link) + strbuf_rtrim(referent); + + is_referent_root = is_root_ref(referent->buf); + if (!is_referent_root && + !starts_with(referent->buf, "refs/") && + !starts_with(referent->buf, "worktrees/")) { + ret = fsck_report_ref(o, report, + FSCK_MSG_SYMREF_TARGET_IS_NOT_A_REF, + "points to non-ref target '%s'", referent->buf); + + } + + if (!is_referent_root && check_refname_format(referent->buf, 0)) { + ret = fsck_report_ref(o, report, + FSCK_MSG_BAD_REFERENT_NAME, + "points to invalid refname '%s'", referent->buf); + goto out; + } + + if (symbolic_link) + goto out; + + if (referent->len == orig_len || + (referent->len < orig_len && orig_last_byte != '\n')) { + ret = fsck_report_ref(o, report, + FSCK_MSG_REF_MISSING_NEWLINE, + "misses LF at the end"); + } + + if (referent->len != orig_len && referent->len != orig_len - 1) { + ret = fsck_report_ref(o, report, + FSCK_MSG_TRAILING_REF_CONTENT, + "has trailing whitespaces or newlines"); + } + +out: + return ret; +} + +static int files_fsck_refs_content(struct ref_store *ref_store, + struct fsck_options *o, + const char *target_name, + struct dir_iterator *iter) +{ + struct strbuf ref_content = STRBUF_INIT; + struct strbuf abs_gitdir = STRBUF_INIT; + struct strbuf referent = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + const char *trailing = NULL; + unsigned int type = 0; + int failure_errno = 0; + struct object_id oid; + int ret = 0; + + report.path = target_name; + + if (S_ISLNK(iter->st.st_mode)) { + const char *relative_referent_path = NULL; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_SYMLINK_REF, + "use deprecated symbolic link for symref"); + + strbuf_add_absolute_path(&abs_gitdir, ref_store->repo->gitdir); + strbuf_normalize_path(&abs_gitdir); + if (!is_dir_sep(abs_gitdir.buf[abs_gitdir.len - 1])) + strbuf_addch(&abs_gitdir, '/'); + + strbuf_add_real_path(&ref_content, iter->path.buf); + skip_prefix(ref_content.buf, abs_gitdir.buf, + &relative_referent_path); + + if (relative_referent_path) + strbuf_addstr(&referent, relative_referent_path); + else + strbuf_addbuf(&referent, &ref_content); + + ret |= files_fsck_symref_target(o, &report, &referent, 1); + goto cleanup; + } + + if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) { + /* + * Ref file could be removed by another concurrent process. We should + * ignore this error and continue to the next ref. + */ + if (errno == ENOENT) + goto cleanup; + + ret = error_errno(_("cannot read ref file '%s'"), iter->path.buf); + goto cleanup; + } + + if (parse_loose_ref_contents(ref_store->repo->hash_algo, + ref_content.buf, &oid, &referent, + &type, &trailing, &failure_errno)) { + strbuf_rtrim(&ref_content); + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_CONTENT, + "%s", ref_content.buf); + goto cleanup; + } + + if (!(type & REF_ISSYMREF)) { + if (!*trailing) { + ret = fsck_report_ref(o, &report, + FSCK_MSG_REF_MISSING_NEWLINE, + "misses LF at the end"); + goto cleanup; + } + if (*trailing != '\n' || *(trailing + 1)) { + ret = fsck_report_ref(o, &report, + FSCK_MSG_TRAILING_REF_CONTENT, + "has trailing garbage: '%s'", trailing); + goto cleanup; + } + } else { + ret = files_fsck_symref_target(o, &report, &referent, 0); + goto cleanup; + } + +cleanup: + strbuf_release(&ref_content); + strbuf_release(&referent); + strbuf_release(&abs_gitdir); + return ret; +} + +static int files_fsck_refs_name(struct ref_store *ref_store UNUSED, + struct fsck_options *o, + const char *refname, + struct dir_iterator *iter) +{ + struct strbuf sb = STRBUF_INIT; + int ret = 0; + + /* + * Ignore the files ending with ".lock" as they may be lock files + * However, do not allow bare ".lock" files. + */ + if (iter->basename[0] != '.' && ends_with(iter->basename, ".lock")) + goto cleanup; + + /* + * This works right now because we never check the root refs. + */ + if (check_refname_format(refname, 0)) { + struct fsck_ref_report report = { 0 }; + + report.path = refname; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_NAME, + "invalid refname format"); + } + +cleanup: + strbuf_release(&sb); + return ret; +} + +static int files_fsck_refs_dir(struct ref_store *ref_store, + struct fsck_options *o, + const char *refs_check_dir, + struct worktree *wt, + files_fsck_refs_fn *fsck_refs_fn) +{ + struct strbuf refname = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; + struct dir_iterator *iter; + int iter_status; + int ret = 0; + + strbuf_addf(&sb, "%s/%s", ref_store->gitdir, refs_check_dir); + + iter = dir_iterator_begin(sb.buf, 0); + if (!iter) { + ret = error_errno(_("cannot open directory %s"), sb.buf); + goto out; + } + + while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) { + if (S_ISDIR(iter->st.st_mode)) { + continue; + } else if (S_ISREG(iter->st.st_mode) || + S_ISLNK(iter->st.st_mode)) { + strbuf_reset(&refname); + + if (!is_main_worktree(wt)) + strbuf_addf(&refname, "worktrees/%s/", wt->id); + strbuf_addf(&refname, "%s/%s", refs_check_dir, + iter->relative_path); + + if (o->verbose) + fprintf_ln(stderr, "Checking %s", refname.buf); + + for (size_t i = 0; fsck_refs_fn[i]; i++) { + if (fsck_refs_fn[i](ref_store, o, refname.buf, iter)) + ret = -1; + } + } else { + struct fsck_ref_report report = { .path = iter->basename }; + if (fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "unexpected file type")) + ret = -1; + } + } + + if (iter_status != ITER_DONE) + ret = error(_("failed to iterate over '%s'"), sb.buf); + +out: + strbuf_release(&sb); + strbuf_release(&refname); + return ret; +} + +static int files_fsck_refs(struct ref_store *ref_store, + struct fsck_options *o, + struct worktree *wt) +{ + files_fsck_refs_fn fsck_refs_fn[]= { + files_fsck_refs_name, + files_fsck_refs_content, + NULL, + }; + + if (o->verbose) + fprintf_ln(stderr, _("Checking references consistency")); + return files_fsck_refs_dir(ref_store, o, "refs", wt, fsck_refs_fn); +} + +static int files_fsck(struct ref_store *ref_store, + struct fsck_options *o, + struct worktree *wt) +{ + struct files_ref_store *refs = + files_downcast(ref_store, REF_STORE_READ, "fsck"); + + return files_fsck_refs(ref_store, o, wt) | + refs->packed_ref_store->be->fsck(refs->packed_ref_store, o, wt); +} + struct ref_storage_be refs_be_files = { .name = "files", .init = files_ref_store_init, @@ -3418,7 +3803,6 @@ struct ref_storage_be refs_be_files = { .transaction_prepare = files_transaction_prepare, .transaction_finish = files_transaction_finish, .transaction_abort = files_transaction_abort, - .initial_transaction_commit = files_initial_transaction_commit, .pack_refs = files_pack_refs, .rename_ref = files_rename_ref, @@ -3434,5 +3818,7 @@ struct ref_storage_be refs_be_files = { .reflog_exists = files_reflog_exists, .create_reflog = files_create_reflog, .delete_reflog = files_delete_reflog, - .reflog_expire = files_reflog_expire + .reflog_expire = files_reflog_expire, + + .fsck = files_fsck, }; diff --git a/refs/iterator.c b/refs/iterator.c index d355ebf0d5..8e999d81fc 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -29,6 +29,7 @@ void base_ref_iterator_init(struct ref_iterator *iter, { iter->vtable = vtable; iter->refname = NULL; + iter->referent = NULL; iter->oid = NULL; iter->flags = 0; } @@ -199,6 +200,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) } if (selection & ITER_YIELD_CURRENT) { + iter->base.referent = (*iter->current)->referent; iter->base.refname = (*iter->current)->refname; iter->base.oid = (*iter->current)->oid; iter->base.flags = (*iter->current)->flags; @@ -448,7 +450,7 @@ int do_for_each_ref_iterator(struct ref_iterator *iter, current_ref_iter = iter; while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - retval = fn(iter->refname, iter->oid, iter->flags, cb_data); + retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data); if (retval) { /* * If ref_iterator_abort() returns ITER_ERROR, diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a0666407cd..3406f1e71d 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -13,6 +13,7 @@ #include "../lockfile.h" #include "../chdir-notify.h" #include "../statinfo.h" +#include "../worktree.h" #include "../wrapper.h" #include "../write-or-die.h" #include "../trace2.h" @@ -794,7 +795,7 @@ static int packed_read_raw_ref(struct ref_store *ref_store, const char *refname, return -1; } - if (get_oid_hex(rec, oid)) + if (get_oid_hex_algop(rec, oid, ref_store->repo->hash_algo)) die_invalid_line(refs->path, rec, snapshot->eof - rec); *type = REF_ISPACKED; @@ -879,7 +880,7 @@ static int next_record(struct packed_ref_iterator *iter) p = iter->pos; if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 || - parse_oid_hex(p, &iter->oid, &p) || + parse_oid_hex_algop(p, &iter->oid, &p, iter->repo->hash_algo) || !isspace(*p++)) die_invalid_line(iter->snapshot->refs->path, iter->pos, iter->eof - iter->pos); @@ -896,7 +897,7 @@ static int next_record(struct packed_ref_iterator *iter) if (!refname_is_safe(iter->base.refname)) die("packed refname is dangerous: %s", iter->base.refname); - oidclr(&iter->oid, the_repository->hash_algo); + oidclr(&iter->oid, iter->repo->hash_algo); iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN; } if (iter->snapshot->peeled == PEELED_FULLY || @@ -909,7 +910,7 @@ static int next_record(struct packed_ref_iterator *iter) if (iter->pos < iter->eof && *iter->pos == '^') { p = iter->pos + 1; if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 1 || - parse_oid_hex(p, &iter->peeled, &p) || + parse_oid_hex_algop(p, &iter->peeled, &p, iter->repo->hash_algo) || *p++ != '\n') die_invalid_line(iter->snapshot->refs->path, iter->pos, iter->eof - iter->pos); @@ -921,13 +922,13 @@ static int next_record(struct packed_ref_iterator *iter) * we suppress it if the reference is broken: */ if ((iter->base.flags & REF_ISBROKEN)) { - oidclr(&iter->peeled, the_repository->hash_algo); + oidclr(&iter->peeled, iter->repo->hash_algo); iter->base.flags &= ~REF_KNOWS_PEELED; } else { iter->base.flags |= REF_KNOWS_PEELED; } } else { - oidclr(&iter->peeled, the_repository->hash_algo); + oidclr(&iter->peeled, iter->repo->hash_algo); } return ITER_OK; @@ -1250,6 +1251,24 @@ int packed_refs_is_locked(struct ref_store *ref_store) return is_lock_file_locked(&refs->lock); } +int packed_refs_size(struct ref_store *ref_store, + size_t *out) +{ + struct packed_ref_store *refs = packed_downcast(ref_store, REF_STORE_READ, + "packed_refs_size"); + struct stat st; + + if (stat(refs->path, &st) < 0) { + if (errno != ENOENT) + return -1; + *out = 0; + return 0; + } + + *out = st.st_size; + return 0; +} + /* * The packed-refs header line that we write out. Perhaps other traits * will be added later. @@ -1712,13 +1731,6 @@ cleanup: return ret; } -static int packed_initial_transaction_commit(struct ref_store *ref_store UNUSED, - struct ref_transaction *transaction, - struct strbuf *err) -{ - return ref_transaction_commit(transaction, err); -} - static int packed_pack_refs(struct ref_store *ref_store UNUSED, struct pack_refs_opts *pack_opts UNUSED) { @@ -1735,6 +1747,17 @@ 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, + struct worktree *wt) +{ + + if (!is_main_worktree(wt)) + return 0; + + return 0; +} + struct ref_storage_be refs_be_packed = { .name = "packed", .init = packed_ref_store_init, @@ -1745,7 +1768,6 @@ struct ref_storage_be refs_be_packed = { .transaction_prepare = packed_transaction_prepare, .transaction_finish = packed_transaction_finish, .transaction_abort = packed_transaction_abort, - .initial_transaction_commit = packed_initial_transaction_commit, .pack_refs = packed_pack_refs, .rename_ref = NULL, @@ -1762,4 +1784,6 @@ struct ref_storage_be refs_be_packed = { .create_reflog = NULL, .delete_reflog = NULL, .reflog_expire = NULL, + + .fsck = packed_fsck, }; diff --git a/refs/packed-backend.h b/refs/packed-backend.h index 09437ad13b..9481d5e7c2 100644 --- a/refs/packed-backend.h +++ b/refs/packed-backend.h @@ -28,6 +28,13 @@ void packed_refs_unlock(struct ref_store *ref_store); int packed_refs_is_locked(struct ref_store *ref_store); /* + * Obtain the size of the `packed-refs` file. Reports `0` as size in case there + * is no packed-refs file. Returns 0 on success, negative otherwise. + */ +int packed_refs_size(struct ref_store *ref_store, + size_t *out); + +/* * Return true if `transaction` really needs to be carried out against * the specified packed_ref_store, or false if it can be skipped * (i.e., because it is an obvious NOOP). `ref_store` must be locked diff --git a/refs/ref-cache.c b/refs/ref-cache.c index 4ce519bbc8..02f09e4df8 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -34,6 +34,7 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry) } struct ref_entry *create_ref_entry(const char *refname, + const char *referent, const struct object_id *oid, int flag) { struct ref_entry *ref; @@ -41,6 +42,8 @@ struct ref_entry *create_ref_entry(const char *refname, FLEX_ALLOC_STR(ref, name, refname); oidcpy(&ref->u.value.oid, oid); ref->flag = flag; + ref->u.value.referent = xstrdup_or_null(referent); + return ref; } @@ -65,6 +68,8 @@ static void free_ref_entry(struct ref_entry *entry) * trigger the reading of loose refs. */ clear_ref_dir(&entry->u.subdir); + } else { + free(entry->u.value.referent); } free(entry); } @@ -431,6 +436,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) level->index = -1; } else { iter->base.refname = entry->name; + iter->base.referent = entry->u.value.referent; iter->base.oid = &entry->u.value.oid; iter->base.flags = entry->flag; return ITER_OK; diff --git a/refs/ref-cache.h b/refs/ref-cache.h index 31ebe24f6c..5f04e518c3 100644 --- a/refs/ref-cache.h +++ b/refs/ref-cache.h @@ -42,6 +42,7 @@ struct ref_value { * referred to by the last reference in the symlink chain. */ struct object_id oid; + char *referent; }; /* @@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache, const char *dirname, size_t len); struct ref_entry *create_ref_entry(const char *refname, + const char *referent, const struct object_id *oid, int flag); /* diff --git a/refs/refs-internal.h b/refs/refs-internal.h index fa975d69aa..58aa56d1b2 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -4,6 +4,7 @@ #include "refs.h" #include "iterator.h" +struct fsck_options; struct ref_transaction; /* @@ -192,6 +193,7 @@ struct ref_transaction { size_t nr; enum ref_transaction_state state; void *backend_data; + unsigned int flags; }; /* @@ -299,6 +301,7 @@ enum do_for_each_ref_flags { struct ref_iterator { struct ref_iterator_vtable *vtable; const char *refname; + const char *referent; const struct object_id *oid; unsigned int flags; }; @@ -650,6 +653,10 @@ typedef int read_raw_ref_fn(struct ref_store *ref_store, const char *refname, typedef int read_symbolic_ref_fn(struct ref_store *ref_store, const char *refname, struct strbuf *referent); +typedef int fsck_fn(struct ref_store *ref_store, + struct fsck_options *o, + struct worktree *wt); + struct ref_storage_be { const char *name; ref_store_init_fn *init; @@ -660,7 +667,6 @@ struct ref_storage_be { ref_transaction_prepare_fn *transaction_prepare; ref_transaction_finish_fn *transaction_finish; ref_transaction_abort_fn *transaction_abort; - ref_transaction_commit_fn *initial_transaction_commit; pack_refs_fn *pack_refs; rename_ref_fn *rename_ref; @@ -677,6 +683,8 @@ struct ref_storage_be { create_reflog_fn *create_reflog; delete_reflog_fn *delete_reflog; reflog_expire_fn *reflog_expire; + + fsck_fn *fsck; }; extern struct ref_storage_be refs_be_files; @@ -705,9 +713,10 @@ struct ref_store { * Parse contents of a loose ref file. *failure_errno maybe be set to EINVAL for * invalid contents. */ -int parse_loose_ref_contents(const char *buf, struct object_id *oid, +int parse_loose_ref_contents(const struct git_hash_algo *algop, + const char *buf, struct object_id *oid, struct strbuf *referent, unsigned int *type, - int *failure_errno); + const char **trailing, int *failure_errno); /* * Fill in the generic part of refs and add it to our collection of diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index fbe74c239d..31c58db29f 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -15,12 +15,16 @@ #include "../object.h" #include "../path.h" #include "../refs.h" +#include "../reftable/reftable-basics.h" #include "../reftable/reftable-stack.h" #include "../reftable/reftable-record.h" #include "../reftable/reftable-error.h" #include "../reftable/reftable-iterator.h" +#include "../repo-settings.h" #include "../setup.h" #include "../strmap.h" +#include "../trace2.h" +#include "../write-or-die.h" #include "parse.h" #include "refs-internal.h" @@ -30,27 +34,115 @@ */ #define REF_UPDATE_VIA_HEAD (1 << 8) +struct reftable_backend { + struct reftable_stack *stack; + struct reftable_iterator it; +}; + +static void reftable_backend_on_reload(void *payload) +{ + struct reftable_backend *be = payload; + reftable_iterator_destroy(&be->it); +} + +static int reftable_backend_init(struct reftable_backend *be, + const char *path, + const struct reftable_write_options *_opts) +{ + struct reftable_write_options opts = *_opts; + opts.on_reload = reftable_backend_on_reload; + opts.on_reload_payload = be; + return reftable_new_stack(&be->stack, path, &opts); +} + +static void reftable_backend_release(struct reftable_backend *be) +{ + reftable_stack_destroy(be->stack); + be->stack = NULL; + reftable_iterator_destroy(&be->it); +} + +static int reftable_backend_read_ref(struct reftable_backend *be, + const char *refname, + struct object_id *oid, + struct strbuf *referent, + unsigned int *type) +{ + struct reftable_ref_record ref = {0}; + int ret; + + if (!be->it.ops) { + ret = reftable_stack_init_ref_iterator(be->stack, &be->it); + if (ret) + goto done; + } + + ret = reftable_iterator_seek_ref(&be->it, refname); + if (ret) + goto done; + + ret = reftable_iterator_next_ref(&be->it, &ref); + if (ret) + goto done; + + if (strcmp(ref.refname, refname)) { + ret = 1; + goto done; + } + + if (ref.value_type == REFTABLE_REF_SYMREF) { + strbuf_reset(referent); + strbuf_addstr(referent, ref.value.symref); + *type |= REF_ISSYMREF; + } else if (reftable_ref_record_val1(&ref)) { + unsigned int hash_id; + + switch (reftable_stack_hash_id(be->stack)) { + case REFTABLE_HASH_SHA1: + hash_id = GIT_HASH_SHA1; + break; + case REFTABLE_HASH_SHA256: + hash_id = GIT_HASH_SHA256; + break; + default: + BUG("unhandled hash ID %d", reftable_stack_hash_id(be->stack)); + } + + oidread(oid, reftable_ref_record_val1(&ref), + &hash_algos[hash_id]); + } else { + /* We got a tombstone, which should not happen. */ + BUG("unhandled reference value type %d", ref.value_type); + } + +done: + assert(ret != REFTABLE_API_ERROR); + reftable_ref_record_release(&ref); + return ret; +} + struct reftable_ref_store { struct ref_store base; /* - * The main stack refers to the common dir and thus contains common + * The main backend refers to the common dir and thus contains common * refs as well as refs of the main repository. */ - struct reftable_stack *main_stack; + struct reftable_backend main_backend; /* - * The worktree stack refers to the gitdir in case the refdb is opened + * The worktree backend refers to the gitdir in case the refdb is opened * via a worktree. It thus contains the per-worktree refs. */ - struct reftable_stack *worktree_stack; + struct reftable_backend worktree_backend; /* - * Map of worktree stacks by their respective worktree names. The map + * Map of worktree backends by their respective worktree names. The map * is populated lazily when we try to resolve `worktrees/$worktree` refs. */ - struct strmap worktree_stacks; + struct strmap worktree_backends; struct reftable_write_options write_options; unsigned int store_flags; + enum log_refs_config log_all_ref_updates; int err; }; @@ -92,21 +184,25 @@ static struct reftable_ref_store *reftable_be_downcast(struct ref_store *ref_sto * like `worktrees/$worktree/refs/heads/foo` as worktree stacks will store * those references in their normalized form. */ -static struct reftable_stack *stack_for(struct reftable_ref_store *store, - const char *refname, - const char **rewritten_ref) +static int backend_for(struct reftable_backend **out, + struct reftable_ref_store *store, + const char *refname, + const char **rewritten_ref, + int reload) { + struct reftable_backend *be; const char *wtname; int wtname_len; - if (!refname) - return store->main_stack; + if (!refname) { + be = &store->main_backend; + goto out; + } switch (parse_worktree_ref(refname, &wtname, &wtname_len, rewritten_ref)) { case REF_WORKTREE_OTHER: { static struct strbuf wtname_buf = STRBUF_INIT; struct strbuf wt_dir = STRBUF_INIT; - struct reftable_stack *stack; /* * We're using a static buffer here so that we don't need to @@ -120,58 +216,74 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store, /* * There is an edge case here: when the worktree references the * current worktree, then we set up the stack once via - * `worktree_stacks` and once via `worktree_stack`. This is + * `worktree_backends` and once via `worktree_backend`. This is * wasteful, but in the reading case it shouldn't matter. And * in the writing case we would notice that the stack is locked * already and error out when trying to write a reference via * both stacks. */ - stack = strmap_get(&store->worktree_stacks, wtname_buf.buf); - if (!stack) { + be = strmap_get(&store->worktree_backends, wtname_buf.buf); + if (!be) { strbuf_addf(&wt_dir, "%s/worktrees/%s/reftable", store->base.repo->commondir, wtname_buf.buf); - store->err = reftable_new_stack(&stack, wt_dir.buf, - &store->write_options); + CALLOC_ARRAY(be, 1); + store->err = reftable_backend_init(be, wt_dir.buf, + &store->write_options); assert(store->err != REFTABLE_API_ERROR); - strmap_put(&store->worktree_stacks, wtname_buf.buf, stack); + + strmap_put(&store->worktree_backends, wtname_buf.buf, be); } strbuf_release(&wt_dir); - return stack; + goto out; } case REF_WORKTREE_CURRENT: /* * If there is no worktree stack then we're currently in the * main worktree. We thus return the main stack in that case. */ - if (!store->worktree_stack) - return store->main_stack; - return store->worktree_stack; + if (!store->worktree_backend.stack) + be = &store->main_backend; + else + be = &store->worktree_backend; + goto out; case REF_WORKTREE_MAIN: case REF_WORKTREE_SHARED: - return store->main_stack; + be = &store->main_backend; + goto out; default: BUG("unhandled worktree reference type"); } + +out: + if (reload) { + int ret = reftable_stack_reload(be->stack); + if (ret) + return ret; + } + *out = be; + + return 0; } -static int should_write_log(struct ref_store *refs, const char *refname) +static int should_write_log(struct reftable_ref_store *refs, const char *refname) { - if (log_all_ref_updates == LOG_REFS_UNSET) - log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; + enum log_refs_config log_refs_cfg = refs->log_all_ref_updates; + if (log_refs_cfg == LOG_REFS_UNSET) + log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; - switch (log_all_ref_updates) { + switch (log_refs_cfg) { case LOG_REFS_NONE: - return refs_reflog_exists(refs, refname); + return refs_reflog_exists(&refs->base, refname); case LOG_REFS_ALWAYS: return 1; case LOG_REFS_NORMAL: - if (should_autocreate_reflog(refname)) + if (should_autocreate_reflog(log_refs_cfg, refname)) return 1; - return refs_reflog_exists(refs, refname); + return refs_reflog_exists(&refs->base, refname); default: - BUG("unhandled core.logAllRefUpdates value %d", log_all_ref_updates); + BUG("unhandled core.logAllRefUpdates value %d", log_refs_cfg); } } @@ -201,37 +313,6 @@ static void fill_reftable_log_record(struct reftable_log_record *log, const stru log->value.update.tz_offset = sign * atoi(tz_begin); } -static int read_ref_without_reload(struct reftable_stack *stack, - const char *refname, - struct object_id *oid, - struct strbuf *referent, - unsigned int *type) -{ - struct reftable_ref_record ref = {0}; - int ret; - - ret = reftable_stack_read_ref(stack, refname, &ref); - if (ret) - goto done; - - if (ref.value_type == REFTABLE_REF_SYMREF) { - strbuf_reset(referent); - strbuf_addstr(referent, ref.value.symref); - *type |= REF_ISSYMREF; - } else if (reftable_ref_record_val1(&ref)) { - oidread(oid, reftable_ref_record_val1(&ref), - the_repository->hash_algo); - } else { - /* We got a tombstone, which should not happen. */ - BUG("unhandled reference value type %d", ref.value_type); - } - -done: - assert(ret != REFTABLE_API_ERROR); - reftable_ref_record_release(&ref); - return ret; -} - static int reftable_be_config(const char *var, const char *value, const struct config_context *ctx, void *_opts) @@ -255,11 +336,23 @@ static int reftable_be_config(const char *var, const char *value, if (factor > UINT8_MAX) die("reftable geometric factor cannot exceed %u", (unsigned)UINT8_MAX); opts->auto_compaction_factor = factor; + } else if (!strcmp(var, "reftable.locktimeout")) { + int64_t lock_timeout = git_config_int64(var, value, ctx->kvi); + if (lock_timeout > LONG_MAX) + die("reftable lock timeout cannot exceed %"PRIdMAX, (intmax_t)LONG_MAX); + if (lock_timeout < 0 && lock_timeout != -1) + die("reftable lock timeout does not support negative values other than -1"); + opts->lock_timeout_ms = lock_timeout; } return 0; } +static int reftable_be_fsync(int fd) +{ + return fsync_component(FSYNC_COMPONENT_REFERENCE, fd); +} + static struct ref_store *reftable_be_init(struct repository *repo, const char *gitdir, unsigned int store_flags) @@ -273,13 +366,25 @@ static struct ref_store *reftable_be_init(struct repository *repo, umask(mask); base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable); - strmap_init(&refs->worktree_stacks); + strmap_init(&refs->worktree_backends); refs->store_flags = store_flags; + refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); - refs->write_options.hash_id = repo->hash_algo->format_id; + switch (repo->hash_algo->format_id) { + case GIT_SHA1_FORMAT_ID: + refs->write_options.hash_id = REFTABLE_HASH_SHA1; + break; + case GIT_SHA256_FORMAT_ID: + refs->write_options.hash_id = REFTABLE_HASH_SHA256; + break; + default: + BUG("unknown hash algorithm %d", repo->hash_algo->format_id); + } refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); refs->write_options.disable_auto_compact = !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); + refs->write_options.lock_timeout_ms = 100; + refs->write_options.fsync = reftable_be_fsync; git_config(reftable_be_config, &refs->write_options); @@ -306,8 +411,8 @@ static struct ref_store *reftable_be_init(struct repository *repo, strbuf_realpath(&path, gitdir, 0); } strbuf_addstr(&path, "/reftable"); - refs->err = reftable_new_stack(&refs->main_stack, path.buf, - &refs->write_options); + refs->err = reftable_backend_init(&refs->main_backend, path.buf, + &refs->write_options); if (refs->err) goto done; @@ -323,8 +428,8 @@ static struct ref_store *reftable_be_init(struct repository *repo, strbuf_reset(&path); strbuf_addf(&path, "%s/reftable", gitdir); - refs->err = reftable_new_stack(&refs->worktree_stack, path.buf, - &refs->write_options); + refs->err = reftable_backend_init(&refs->worktree_backend, path.buf, + &refs->write_options); if (refs->err) goto done; } @@ -343,19 +448,17 @@ static void reftable_be_release(struct ref_store *ref_store) struct strmap_entry *entry; struct hashmap_iter iter; - if (refs->main_stack) { - reftable_stack_destroy(refs->main_stack); - refs->main_stack = NULL; - } + if (refs->main_backend.stack) + reftable_backend_release(&refs->main_backend); + if (refs->worktree_backend.stack) + reftable_backend_release(&refs->worktree_backend); - if (refs->worktree_stack) { - reftable_stack_destroy(refs->worktree_stack); - refs->worktree_stack = NULL; + strmap_for_each_entry(&refs->worktree_backends, &iter, entry) { + struct reftable_backend *be = entry->value; + reftable_backend_release(be); + free(be); } - - strmap_for_each_entry(&refs->worktree_stacks, &iter, entry) - reftable_stack_destroy(entry->value); - strmap_clear(&refs->worktree_stacks, 0); + strmap_clear(&refs->worktree_backends, 0); } static int reftable_be_create_on_disk(struct ref_store *ref_store, @@ -446,15 +549,87 @@ struct reftable_ref_iterator { const char *prefix; size_t prefix_len; + char **exclude_patterns; + size_t exclude_patterns_index; + size_t exclude_patterns_strlen; unsigned int flags; int err; }; +/* + * Handle exclude patterns. Returns either `1`, which tells the caller that the + * current reference shall not be shown. Or `0`, which indicates that it should + * be shown. + */ +static int should_exclude_current_ref(struct reftable_ref_iterator *iter) +{ + while (iter->exclude_patterns[iter->exclude_patterns_index]) { + const char *pattern = iter->exclude_patterns[iter->exclude_patterns_index]; + char *ref_after_pattern; + int cmp; + + /* + * Lazily cache the pattern length so that we don't have to + * recompute it every time this function is called. + */ + if (!iter->exclude_patterns_strlen) + iter->exclude_patterns_strlen = strlen(pattern); + + /* + * When the reference name is lexicographically bigger than the + * current exclude pattern we know that it won't ever match any + * of the following references, either. We thus advance to the + * next pattern and re-check whether it matches. + * + * Otherwise, if it's smaller, then we do not have a match and + * thus want to show the current reference. + */ + cmp = strncmp(iter->ref.refname, pattern, + iter->exclude_patterns_strlen); + if (cmp > 0) { + iter->exclude_patterns_index++; + iter->exclude_patterns_strlen = 0; + continue; + } + if (cmp < 0) + return 0; + + /* + * The reference shares a prefix with the exclude pattern and + * shall thus be omitted. We skip all references that match the + * pattern by seeking to the first reference after the block of + * matches. + * + * This is done by appending the highest possible character to + * the pattern. Consequently, all references that have the + * pattern as prefix and whose suffix starts with anything in + * the range [0x00, 0xfe] are skipped. And given that 0xff is a + * non-printable character that shouldn't ever be in a ref name, + * we'd not yield any such record, either. + * + * Note that the seeked-to reference may also be excluded. This + * is not handled here though, but the caller is expected to + * loop and re-verify the next reference for us. + */ + ref_after_pattern = xstrfmt("%s%c", pattern, 0xff); + iter->err = reftable_iterator_seek_ref(&iter->iter, ref_after_pattern); + iter->exclude_patterns_index++; + iter->exclude_patterns_strlen = 0; + trace2_counter_add(TRACE2_COUNTER_ID_REFTABLE_RESEEKS, 1); + + free(ref_after_pattern); + return 1; + } + + return 0; +} + static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) { struct reftable_ref_iterator *iter = (struct reftable_ref_iterator *)ref_iterator; struct reftable_ref_store *refs = iter->refs; + const char *referent = NULL; while (!iter->err) { int flags = 0; @@ -479,6 +654,9 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) break; } + if (iter->exclude_patterns && should_exclude_current_ref(iter)) + continue; + if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY && parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) != REF_WORKTREE_CURRENT) @@ -487,16 +665,19 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) switch (iter->ref.value_type) { case REFTABLE_REF_VAL1: oidread(&iter->oid, iter->ref.value.val1, - the_repository->hash_algo); + refs->base.repo->hash_algo); break; case REFTABLE_REF_VAL2: oidread(&iter->oid, iter->ref.value.val2.value, - the_repository->hash_algo); + refs->base.repo->hash_algo); break; case REFTABLE_REF_SYMREF: - if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, - RESOLVE_REF_READING, &iter->oid, &flags)) - oidclr(&iter->oid, the_repository->hash_algo); + referent = refs_resolve_ref_unsafe(&iter->refs->base, + iter->ref.refname, + RESOLVE_REF_READING, + &iter->oid, &flags); + if (!referent) + oidclr(&iter->oid, refs->base.repo->hash_algo); break; default: BUG("unhandled reference value type %d", iter->ref.value_type); @@ -508,7 +689,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) if (check_refname_format(iter->ref.refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(iter->ref.refname)) die(_("refname is dangerous: %s"), iter->ref.refname); - oidclr(&iter->oid, the_repository->hash_algo); + oidclr(&iter->oid, refs->base.repo->hash_algo); flags |= REF_BAD_NAME | REF_ISBROKEN; } @@ -523,6 +704,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) continue; iter->base.refname = iter->ref.refname; + iter->base.referent = referent; iter->base.oid = &iter->oid; iter->base.flags = flags; @@ -551,7 +733,7 @@ static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, if (iter->ref.value_type == REFTABLE_REF_VAL2) { oidread(peeled, iter->ref.value.val2.target_value, - the_repository->hash_algo); + iter->refs->base.repo->hash_algo); return 0; } @@ -564,6 +746,11 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) (struct reftable_ref_iterator *)ref_iterator; reftable_ref_record_release(&iter->ref); reftable_iterator_destroy(&iter->iter); + if (iter->exclude_patterns) { + for (size_t i = 0; iter->exclude_patterns[i]; i++) + free(iter->exclude_patterns[i]); + free(iter->exclude_patterns); + } free(iter); return ITER_DONE; } @@ -574,9 +761,53 @@ static struct ref_iterator_vtable reftable_ref_iterator_vtable = { .abort = reftable_ref_iterator_abort }; +static int qsort_strcmp(const void *va, const void *vb) +{ + const char *a = *(const char **)va; + const char *b = *(const char **)vb; + return strcmp(a, b); +} + +static char **filter_exclude_patterns(const char **exclude_patterns) +{ + size_t filtered_size = 0, filtered_alloc = 0; + char **filtered = NULL; + + if (!exclude_patterns) + return NULL; + + for (size_t i = 0; ; i++) { + const char *exclude_pattern = exclude_patterns[i]; + int has_glob = 0; + + if (!exclude_pattern) + break; + + for (const char *p = exclude_pattern; *p; p++) { + has_glob = is_glob_special(*p); + if (has_glob) + break; + } + if (has_glob) + continue; + + ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc); + filtered[filtered_size++] = xstrdup(exclude_pattern); + } + + if (filtered_size) { + QSORT(filtered, filtered_size, qsort_strcmp); + ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc); + filtered[filtered_size++] = NULL; + } + + return filtered; +} + static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_store *refs, struct reftable_stack *stack, const char *prefix, + const char **exclude_patterns, int flags) { struct reftable_ref_iterator *iter; @@ -589,6 +820,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ iter->base.oid = &iter->oid; iter->flags = flags; iter->refs = refs; + iter->exclude_patterns = filter_exclude_patterns(exclude_patterns); ret = refs->err; if (ret) @@ -621,21 +853,23 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto required_flags |= REF_STORE_ODB; refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin"); - main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix, flags); + main_iter = ref_iterator_for_stack(refs, refs->main_backend.stack, prefix, + exclude_patterns, flags); /* * The worktree stack is only set when we're in an actual worktree * right now. If we aren't, then we return the common reftable * iterator, only. */ - if (!refs->worktree_stack) + if (!refs->worktree_backend.stack) return &main_iter->base; /* * Otherwise we merge both the common and the per-worktree refs into a * single iterator. */ - worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix, flags); + worktree_iter = ref_iterator_for_stack(refs, refs->worktree_backend.stack, prefix, + exclude_patterns, flags); return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base, ref_iterator_select, NULL); } @@ -649,17 +883,17 @@ static int reftable_be_read_raw_ref(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ, "read_raw_ref"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); + struct reftable_backend *be; int ret; if (refs->err < 0) return refs->err; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); if (ret) return ret; - ret = read_ref_without_reload(stack, refname, oid, referent, type); + ret = reftable_backend_read_ref(be, refname, oid, referent, type); if (ret < 0) return ret; if (ret > 0) { @@ -676,21 +910,18 @@ static int reftable_be_read_symbolic_ref(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ, "read_symbolic_ref"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); - struct reftable_ref_record ref = {0}; + struct reftable_backend *be; + struct object_id oid; + unsigned int type = 0; int ret; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); if (ret) return ret; - ret = reftable_stack_read_ref(stack, refname, &ref); - if (ret == 0 && ref.value_type == REFTABLE_REF_SYMREF) - strbuf_addstr(referent, ref.value.symref); - else + ret = reftable_backend_read_ref(be, refname, &oid, referent, &type); + if (type != REF_ISSYMREF) ret = -1; - - reftable_ref_record_release(&ref); return ret; } @@ -701,7 +932,7 @@ struct reftable_transaction_update { struct write_transaction_table_arg { struct reftable_ref_store *refs; - struct reftable_stack *stack; + struct reftable_backend *be; struct reftable_addition *addition; struct reftable_transaction_update *updates; size_t updates_nr; @@ -736,27 +967,38 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out, struct ref_update *update, struct strbuf *err) { - struct reftable_stack *stack = stack_for(refs, update->refname, NULL); struct write_transaction_table_arg *arg = NULL; + struct reftable_backend *be; size_t i; int ret; /* + * This function gets called in a loop, and we don't want to repeatedly + * reload the stack for every single ref update. Instead, we manually + * reload further down in the case where we haven't yet prepared the + * specific `reftable_backend`. + */ + ret = backend_for(&be, refs, update->refname, NULL, 0); + if (ret) + return ret; + + /* * Search for a preexisting stack update. If there is one then we add * the update to it, otherwise we set up a new stack update. */ for (i = 0; !arg && i < tx_data->args_nr; i++) - if (tx_data->args[i].stack == stack) + if (tx_data->args[i].be == be) arg = &tx_data->args[i]; if (!arg) { struct reftable_addition *addition; - ret = reftable_stack_reload(stack); + ret = reftable_stack_reload(be->stack); if (ret) return ret; - ret = reftable_stack_new_addition(&addition, stack); + ret = reftable_stack_new_addition(&addition, be->stack, + REFTABLE_STACK_NEW_ADDITION_RELOAD); if (ret) { if (ret == REFTABLE_LOCK_ERROR) strbuf_addstr(err, "cannot lock references"); @@ -767,7 +1009,7 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out, tx_data->args_alloc); arg = &tx_data->args[tx_data->args_nr++]; arg->refs = refs; - arg->stack = stack; + arg->be = be; arg->addition = addition; arg->updates = NULL; arg->updates_nr = 0; @@ -822,6 +1064,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, struct strbuf referent = STRBUF_INIT, head_referent = STRBUF_INIT; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; struct reftable_transaction_data *tx_data = NULL; + struct reftable_backend *be; struct object_id head_oid; unsigned int head_type = 0; size_t i; @@ -868,8 +1111,23 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, goto done; } - ret = read_ref_without_reload(stack_for(refs, "HEAD", NULL), "HEAD", &head_oid, - &head_referent, &head_type); + /* + * TODO: it's dubious whether we should reload the stack that "HEAD" + * belongs to or not. In theory, it may happen that we only modify + * stacks which are _not_ part of the "HEAD" stack. In that case we + * wouldn't have prepared any transaction for its stack and would not + * have reloaded it, which may mean that it is stale. + * + * On the other hand, reloading that stack without locking it feels + * wrong, too, as the value of "HEAD" could be modified concurrently at + * any point in time. + */ + ret = backend_for(&be, refs, "HEAD", NULL, 0); + if (ret) + goto done; + + ret = reftable_backend_read_ref(be, "HEAD", &head_oid, + &head_referent, &head_type); if (ret < 0) goto done; ret = 0; @@ -877,10 +1135,18 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, for (i = 0; i < transaction->nr; i++) { struct ref_update *u = transaction->updates[i]; struct object_id current_oid = {0}; - struct reftable_stack *stack; const char *rewritten_ref; - stack = stack_for(refs, u->refname, &rewritten_ref); + /* + * There is no need to reload the respective backends here as + * we have already reloaded them when preparing the transaction + * update. And given that the stacks have been locked there + * shouldn't have been any concurrent modifications of the + * stack. + */ + ret = backend_for(&be, refs, u->refname, &rewritten_ref, 0); + if (ret) + goto done; /* Verify that the new object ID is valid. */ if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) && @@ -936,8 +1202,8 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, string_list_insert(&affected_refnames, new_update->refname); } - ret = read_ref_without_reload(stack, rewritten_ref, - ¤t_oid, &referent, &u->type); + ret = reftable_backend_read_ref(be, rewritten_ref, + ¤t_oid, &referent, &u->type); if (ret < 0) goto done; if (ret > 0 && !ref_update_expects_existing_old_ref(u)) { @@ -951,7 +1217,9 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, * at a later point. */ ret = refs_verify_refname_available(ref_store, u->refname, - &affected_refnames, NULL, err); + &affected_refnames, NULL, + transaction->flags & REF_TRANSACTION_FLAG_INITIAL, + err); if (ret < 0) goto done; @@ -1119,9 +1387,9 @@ done: return ret; } -static int reftable_be_transaction_abort(struct ref_store *ref_store, +static int reftable_be_transaction_abort(struct ref_store *ref_store UNUSED, struct ref_transaction *transaction, - struct strbuf *err) + struct strbuf *err UNUSED) { struct reftable_transaction_data *tx_data = transaction->backend_data; free_transaction_data(tx_data); @@ -1138,7 +1406,7 @@ static int transaction_update_cmp(const void *a, const void *b) static int write_transaction_table(struct reftable_writer *writer, void *cb_data) { struct write_transaction_table_arg *arg = cb_data; - uint64_t ts = reftable_stack_next_update_index(arg->stack); + uint64_t ts = reftable_stack_next_update_index(arg->be->stack); struct reftable_log_record *logs = NULL; struct ident_split committer_ident = {0}; size_t logs_nr = 0, logs_alloc = 0, i; @@ -1174,7 +1442,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data struct reftable_log_record log = {0}; struct reftable_iterator it = {0}; - reftable_stack_init_log_iterator(arg->stack, &it); + ret = reftable_stack_init_log_iterator(arg->be->stack, &it); + if (ret < 0) + goto done; /* * When deleting refs we also delete all reflog entries @@ -1212,7 +1482,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data } else if (!(u->flags & REF_SKIP_CREATE_REFLOG) && (u->flags & REF_HAVE_NEW) && (u->flags & REF_FORCE_CREATE_REFLOG || - should_write_log(&arg->refs->base, u->refname))) { + should_write_log(arg->refs, u->refname))) { struct reftable_log_record *log; int create_reflog = 1; @@ -1311,7 +1581,7 @@ done: return ret; } -static int reftable_be_transaction_finish(struct ref_store *ref_store, +static int reftable_be_transaction_finish(struct ref_store *ref_store UNUSED, struct ref_transaction *transaction, struct strbuf *err) { @@ -1342,13 +1612,6 @@ done: return ret; } -static int reftable_be_initial_transaction_commit(struct ref_store *ref_store UNUSED, - struct ref_transaction *transaction, - struct strbuf *err) -{ - return ref_transaction_commit(transaction, err); -} - static int reftable_be_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *opts) { @@ -1360,9 +1623,9 @@ static int reftable_be_pack_refs(struct ref_store *ref_store, if (refs->err) return refs->err; - stack = refs->worktree_stack; + stack = refs->worktree_backend.stack; if (!stack) - stack = refs->main_stack; + stack = refs->main_backend.stack; if (opts->flags & PACK_REFS_AUTO) ret = reftable_stack_auto_compact(stack); @@ -1393,7 +1656,7 @@ struct write_create_symref_arg { struct write_copy_arg { struct reftable_ref_store *refs; - struct reftable_stack *stack; + struct reftable_backend *be; const char *oldname; const char *newname; const char *logmsg; @@ -1418,7 +1681,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) if (split_ident_line(&committer_ident, committer_info, strlen(committer_info))) BUG("failed splitting committer info"); - if (reftable_stack_read_ref(arg->stack, arg->oldname, &old_ref)) { + if (reftable_stack_read_ref(arg->be->stack, arg->oldname, &old_ref)) { ret = error(_("refname %s not found"), arg->oldname); goto done; } @@ -1443,7 +1706,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) if (arg->delete_old) string_list_insert(&skip, arg->oldname); ret = refs_verify_refname_available(&arg->refs->base, arg->newname, - NULL, &skip, &errbuf); + NULL, &skip, 0, &errbuf); if (ret < 0) { error("%s", errbuf.buf); goto done; @@ -1457,7 +1720,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) * the old branch and the creation of the new branch, and we cannot do * two changes to a reflog in a single update. */ - deletion_ts = creation_ts = reftable_stack_next_update_index(arg->stack); + deletion_ts = creation_ts = reftable_stack_next_update_index(arg->be->stack); if (arg->delete_old) creation_ts++; reftable_writer_set_limits(writer, deletion_ts, creation_ts); @@ -1500,7 +1763,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) memcpy(logs[logs_nr].value.update.old_hash, old_ref.value.val1, GIT_MAX_RAWSZ); logs_nr++; - ret = read_ref_without_reload(arg->stack, "HEAD", &head_oid, &head_referent, &head_type); + ret = reftable_backend_read_ref(arg->be, "HEAD", &head_oid, + &head_referent, &head_type); if (ret < 0) goto done; append_head_reflog = (head_type & REF_ISSYMREF) && !strcmp(head_referent.buf, arg->oldname); @@ -1543,7 +1807,10 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data) * copy over all log entries from the old reflog. Last but not least, * when renaming we also have to delete all the old reflog entries. */ - reftable_stack_init_log_iterator(arg->stack, &it); + ret = reftable_stack_init_log_iterator(arg->be->stack, &it); + if (ret < 0) + goto done; + ret = reftable_iterator_seek_log(&it, arg->oldname); if (ret < 0) goto done; @@ -1613,10 +1880,8 @@ static int reftable_be_rename_ref(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_WRITE, "rename_ref"); - struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname); struct write_copy_arg arg = { .refs = refs, - .stack = stack, .oldname = oldrefname, .newname = newrefname, .logmsg = logmsg, @@ -1628,10 +1893,10 @@ static int reftable_be_rename_ref(struct ref_store *ref_store, if (ret < 0) goto done; - ret = reftable_stack_reload(stack); + ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1); if (ret) goto done; - ret = reftable_stack_add(stack, &write_copy_table, &arg); + ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg); done: assert(ret != REFTABLE_API_ERROR); @@ -1645,10 +1910,8 @@ static int reftable_be_copy_ref(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_WRITE, "copy_ref"); - struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname); struct write_copy_arg arg = { .refs = refs, - .stack = stack, .oldname = oldrefname, .newname = newrefname, .logmsg = logmsg, @@ -1659,10 +1922,10 @@ static int reftable_be_copy_ref(struct ref_store *ref_store, if (ret < 0) goto done; - ret = reftable_stack_reload(stack); + ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1); if (ret) goto done; - ret = reftable_stack_add(stack, &write_copy_table, &arg); + ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg); done: assert(ret != REFTABLE_API_ERROR); @@ -1721,8 +1984,8 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } -static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) +static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED, + struct object_id *peeled UNUSED) { BUG("reftable reflog iterator cannot be peeled"); return -1; @@ -1764,7 +2027,10 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl if (ret < 0) goto done; - reftable_stack_init_log_iterator(stack, &iter->iter); + ret = reftable_stack_init_log_iterator(stack, &iter->iter); + if (ret < 0) + goto done; + ret = reftable_iterator_seek_log(&iter->iter, ""); if (ret < 0) goto done; @@ -1780,25 +2046,26 @@ static struct ref_iterator *reftable_be_reflog_iterator_begin(struct ref_store * reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_iterator_begin"); struct reftable_reflog_iterator *main_iter, *worktree_iter; - main_iter = reflog_iterator_for_stack(refs, refs->main_stack); - if (!refs->worktree_stack) + main_iter = reflog_iterator_for_stack(refs, refs->main_backend.stack); + if (!refs->worktree_backend.stack) return &main_iter->base; - worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_stack); + worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_backend.stack); return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base, ref_iterator_select, NULL); } -static int yield_log_record(struct reftable_log_record *log, +static int yield_log_record(struct reftable_ref_store *refs, + struct reftable_log_record *log, each_reflog_ent_fn fn, void *cb_data) { struct object_id old_oid, new_oid; const char *full_committer; - oidread(&old_oid, log->value.update.old_hash, the_repository->hash_algo); - oidread(&new_oid, log->value.update.new_hash, the_repository->hash_algo); + oidread(&old_oid, log->value.update.old_hash, refs->base.repo->hash_algo); + oidread(&new_oid, log->value.update.new_hash, refs->base.repo->hash_algo); /* * When both the old object ID and the new object ID are null @@ -1822,15 +2089,26 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); struct reftable_log_record log = {0}; struct reftable_iterator it = {0}; + struct reftable_backend *be; int ret; if (refs->err < 0) return refs->err; - reftable_stack_init_log_iterator(stack, &it); + /* + * TODO: we should adapt this callsite to reload the stack. There is no + * obvious reason why we shouldn't. + */ + ret = backend_for(&be, refs, refname, &refname, 0); + if (ret) + goto done; + + ret = reftable_stack_init_log_iterator(be->stack, &it); + if (ret < 0) + goto done; + ret = reftable_iterator_seek_log(&it, refname); while (!ret) { ret = reftable_iterator_next_log(&it, &log); @@ -1841,11 +2119,12 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store, break; } - ret = yield_log_record(&log, fn, cb_data); + ret = yield_log_record(refs, &log, fn, cb_data); if (ret) break; } +done: reftable_log_record_release(&log); reftable_iterator_destroy(&it); return ret; @@ -1858,16 +2137,27 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); struct reftable_log_record *logs = NULL; struct reftable_iterator it = {0}; + struct reftable_backend *be; size_t logs_alloc = 0, logs_nr = 0, i; int ret; if (refs->err < 0) return refs->err; - reftable_stack_init_log_iterator(stack, &it); + /* + * TODO: we should adapt this callsite to reload the stack. There is no + * obvious reason why we shouldn't. + */ + ret = backend_for(&be, refs, refname, &refname, 0); + if (ret) + goto done; + + ret = reftable_stack_init_log_iterator(be->stack, &it); + if (ret < 0) + goto done; + ret = reftable_iterator_seek_log(&it, refname); while (!ret) { struct reftable_log_record log = {0}; @@ -1886,7 +2176,7 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store, } for (i = logs_nr; i--;) { - ret = yield_log_record(&logs[i], fn, cb_data); + ret = yield_log_record(refs, &logs[i], fn, cb_data); if (ret) goto done; } @@ -1904,20 +2194,23 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); struct reftable_log_record log = {0}; struct reftable_iterator it = {0}; + struct reftable_backend *be; int ret; ret = refs->err; if (ret < 0) goto done; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); + if (ret < 0) + goto done; + + ret = reftable_stack_init_log_iterator(be->stack, &it); if (ret < 0) goto done; - reftable_stack_init_log_iterator(stack, &it); ret = reftable_iterator_seek_log(&it, refname); if (ret < 0) goto done; @@ -1965,7 +2258,7 @@ static int write_reflog_existence_table(struct reftable_writer *writer, reftable_writer_set_limits(writer, ts, ts); /* - * The existence entry has both old and new object ID set to the the + * The existence entry has both old and new object ID set to the * null object ID. Our iterators are aware of this and will not present * them to their callers. */ @@ -1982,14 +2275,13 @@ done: static int reftable_be_create_reflog(struct ref_store *ref_store, const char *refname, - struct strbuf *errmsg) + struct strbuf *errmsg UNUSED) { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_reflog"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); + struct reftable_backend *be; struct write_reflog_existence_arg arg = { .refs = refs, - .stack = stack, .refname = refname, }; int ret; @@ -1998,11 +2290,12 @@ static int reftable_be_create_reflog(struct ref_store *ref_store, if (ret < 0) goto done; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); if (ret) goto done; + arg.stack = be->stack; - ret = reftable_stack_add(stack, &write_reflog_existence_table, &arg); + ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg); done: return ret; @@ -2023,7 +2316,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da reftable_writer_set_limits(writer, ts, ts); - reftable_stack_init_log_iterator(arg->stack, &it); + ret = reftable_stack_init_log_iterator(arg->stack, &it); + if (ret < 0) + goto out; /* * In order to delete a table we need to delete all reflog entries one @@ -2047,6 +2342,7 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da ret = reftable_writer_add_log(writer, &tombstone); } +out: reftable_log_record_release(&log); reftable_iterator_destroy(&it); return ret; @@ -2057,17 +2353,18 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store, { struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_WRITE, "delete_reflog"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); + struct reftable_backend *be; struct write_reflog_delete_arg arg = { - .stack = stack, .refname = refname, }; int ret; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); if (ret) return ret; - ret = reftable_stack_add(stack, &write_reflog_delete_table, &arg); + arg.stack = be->stack; + + ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg); assert(ret != REFTABLE_API_ERROR); return ret; @@ -2166,41 +2463,41 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, */ struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire"); - struct reftable_stack *stack = stack_for(refs, refname, &refname); struct reftable_log_record *logs = NULL; struct reftable_log_record *rewritten = NULL; - struct reftable_ref_record ref_record = {0}; struct reftable_iterator it = {0}; struct reftable_addition *add = NULL; struct reflog_expiry_arg arg = {0}; + struct reftable_backend *be; struct object_id oid = {0}; + struct strbuf referent = STRBUF_INIT; uint8_t *last_hash = NULL; size_t logs_nr = 0, logs_alloc = 0, i; + unsigned int type = 0; int ret; if (refs->err < 0) return refs->err; - ret = reftable_stack_reload(stack); + ret = backend_for(&be, refs, refname, &refname, 1); if (ret < 0) goto done; - reftable_stack_init_log_iterator(stack, &it); + ret = reftable_stack_init_log_iterator(be->stack, &it); + if (ret < 0) + goto done; ret = reftable_iterator_seek_log(&it, refname); if (ret < 0) goto done; - ret = reftable_stack_new_addition(&add, stack); + ret = reftable_stack_new_addition(&add, be->stack, 0); if (ret < 0) goto done; - ret = reftable_stack_read_ref(stack, refname, &ref_record); + ret = reftable_backend_read_ref(be, refname, &oid, &referent, &type); if (ret < 0) goto done; - if (reftable_ref_record_val1(&ref_record)) - oidread(&oid, reftable_ref_record_val1(&ref_record), - the_repository->hash_algo); prepare_fn(refname, &oid, policy_cb_data); while (1) { @@ -2216,9 +2513,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, } oidread(&old_oid, log.value.update.old_hash, - the_repository->hash_algo); + ref_store->repo->hash_algo); oidread(&new_oid, log.value.update.new_hash, - the_repository->hash_algo); + ref_store->repo->hash_algo); /* * Skip over the reflog existence marker. We will add it back @@ -2250,9 +2547,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, *dest = logs[i]; oidread(&old_oid, logs[i].value.update.old_hash, - the_repository->hash_algo); + ref_store->repo->hash_algo); oidread(&new_oid, logs[i].value.update.new_hash, - the_repository->hash_algo); + ref_store->repo->hash_algo); if (should_prune_fn(&old_oid, &new_oid, logs[i].value.update.email, (timestamp_t)logs[i].value.update.time, @@ -2267,15 +2564,14 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store, } } - if (flags & EXPIRE_REFLOGS_UPDATE_REF && last_hash && - reftable_ref_record_val1(&ref_record)) - oidread(&arg.update_oid, last_hash, the_repository->hash_algo); + if (flags & EXPIRE_REFLOGS_UPDATE_REF && last_hash && !is_null_oid(&oid)) + oidread(&arg.update_oid, last_hash, ref_store->repo->hash_algo); arg.refs = refs; arg.records = rewritten; arg.len = logs_nr; - arg.stack = stack, - arg.refname = refname, + arg.stack = be->stack; + arg.refname = refname; ret = reftable_addition_add(add, &write_reflog_expiry_table, &arg); if (ret < 0) @@ -2293,16 +2589,23 @@ done: cleanup_fn(policy_cb_data); assert(ret != REFTABLE_API_ERROR); - reftable_ref_record_release(&ref_record); reftable_iterator_destroy(&it); reftable_addition_destroy(add); for (i = 0; i < logs_nr; i++) reftable_log_record_release(&logs[i]); + strbuf_release(&referent); free(logs); free(rewritten); return ret; } +static int reftable_be_fsck(struct ref_store *ref_store UNUSED, + struct fsck_options *o UNUSED, + struct worktree *wt UNUSED) +{ + return 0; +} + struct ref_storage_be refs_be_reftable = { .name = "reftable", .init = reftable_be_init, @@ -2313,7 +2616,6 @@ struct ref_storage_be refs_be_reftable = { .transaction_prepare = reftable_be_transaction_prepare, .transaction_finish = reftable_be_transaction_finish, .transaction_abort = reftable_be_transaction_abort, - .initial_transaction_commit = reftable_be_initial_transaction_commit, .pack_refs = reftable_be_pack_refs, .rename_ref = reftable_be_rename_ref, @@ -2330,4 +2632,6 @@ struct ref_storage_be refs_be_reftable = { .create_reflog = reftable_be_create_reflog, .delete_reflog = reftable_be_delete_reflog, .reflog_expire = reftable_be_reflog_expire, + + .fsck = reftable_be_fsck, }; @@ -153,6 +153,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet int refspec_item_init(struct refspec_item *item, const char *refspec, int fetch) { memset(item, 0, sizeof(*item)); + item->raw = xstrdup(refspec); return parse_refspec(item, refspec, fetch); } @@ -167,6 +168,7 @@ void refspec_item_clear(struct refspec_item *item) { FREE_AND_NULL(item->src); FREE_AND_NULL(item->dst); + FREE_AND_NULL(item->raw); item->force = 0; item->pattern = 0; item->matching = 0; @@ -179,31 +181,29 @@ void refspec_init(struct refspec *rs, int fetch) rs->fetch = fetch; } -static void refspec_append_nodup(struct refspec *rs, char *refspec) +void refspec_append(struct refspec *rs, const char *refspec) { struct refspec_item item; refspec_item_init_or_die(&item, refspec, rs->fetch); ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc); - rs->items[rs->nr++] = item; + rs->items[rs->nr] = item; - ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc); - rs->raw[rs->raw_nr++] = refspec; -} - -void refspec_append(struct refspec *rs, const char *refspec) -{ - refspec_append_nodup(rs, xstrdup(refspec)); + rs->nr++; } void refspec_appendf(struct refspec *rs, const char *fmt, ...) { va_list ap; + char *buf; va_start(ap, fmt); - refspec_append_nodup(rs, xstrvfmt(fmt, ap)); + buf = xstrvfmt(fmt, ap); va_end(ap); + + refspec_append(rs, buf); + free(buf); } void refspec_appendn(struct refspec *rs, const char **refspecs, int nr) @@ -224,12 +224,6 @@ void refspec_clear(struct refspec *rs) rs->alloc = 0; rs->nr = 0; - for (i = 0; i < rs->raw_nr; i++) - free((char *)rs->raw[i]); - FREE_AND_NULL(rs->raw); - rs->raw_alloc = 0; - rs->raw_nr = 0; - rs->fetch = 0; } @@ -26,6 +26,8 @@ struct refspec_item { char *src; char *dst; + + char *raw; }; #define REFSPEC_FETCH 1 @@ -43,10 +45,6 @@ struct refspec { int alloc; int nr; - const char **raw; - int raw_alloc; - int raw_nr; - int fetch; }; diff --git a/reftable/basics.c b/reftable/basics.c index 0058619ca6..7d84a5d62d 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -6,7 +6,142 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ +#define REFTABLE_ALLOW_BANNED_ALLOCATORS #include "basics.h" +#include "reftable-basics.h" +#include "reftable-error.h" + +static void *(*reftable_malloc_ptr)(size_t sz); +static void *(*reftable_realloc_ptr)(void *, size_t); +static void (*reftable_free_ptr)(void *); + +void *reftable_malloc(size_t sz) +{ + if (reftable_malloc_ptr) + return (*reftable_malloc_ptr)(sz); + return malloc(sz); +} + +void *reftable_realloc(void *p, size_t sz) +{ + if (reftable_realloc_ptr) + return (*reftable_realloc_ptr)(p, sz); + return realloc(p, sz); +} + +void reftable_free(void *p) +{ + if (reftable_free_ptr) + reftable_free_ptr(p); + else + free(p); +} + +void *reftable_calloc(size_t nelem, size_t elsize) +{ + void *p; + + if (nelem && elsize > SIZE_MAX / nelem) + return NULL; + + p = reftable_malloc(nelem * elsize); + if (!p) + return NULL; + + memset(p, 0, nelem * elsize); + return p; +} + +char *reftable_strdup(const char *str) +{ + size_t len = strlen(str); + char *result = reftable_malloc(len + 1); + if (!result) + return NULL; + memcpy(result, str, len + 1); + return result; +} + +void reftable_set_alloc(void *(*malloc)(size_t), + void *(*realloc)(void *, size_t), void (*free)(void *)) +{ + reftable_malloc_ptr = malloc; + reftable_realloc_ptr = realloc; + reftable_free_ptr = free; +} + +void reftable_buf_init(struct reftable_buf *buf) +{ + struct reftable_buf empty = REFTABLE_BUF_INIT; + *buf = empty; +} + +void reftable_buf_release(struct reftable_buf *buf) +{ + reftable_free(buf->buf); + reftable_buf_init(buf); +} + +void reftable_buf_reset(struct reftable_buf *buf) +{ + if (buf->alloc) { + buf->len = 0; + buf->buf[0] = '\0'; + } +} + +int reftable_buf_setlen(struct reftable_buf *buf, size_t len) +{ + if (len > buf->len) + return -1; + if (len == buf->len) + return 0; + buf->buf[len] = '\0'; + buf->len = len; + return 0; +} + +int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b) +{ + size_t len = a->len < b->len ? a->len : b->len; + if (len) { + int cmp = memcmp(a->buf, b->buf, len); + if (cmp) + return cmp; + } + return a->len < b->len ? -1 : a->len != b->len; +} + +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len) +{ + size_t newlen = buf->len + len; + + if (newlen + 1 > buf->alloc) { + char *reallocated = buf->buf; + REFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc); + if (!reallocated) + return REFTABLE_OUT_OF_MEMORY_ERROR; + buf->buf = reallocated; + } + + memcpy(buf->buf + buf->len, data, len); + buf->buf[newlen] = '\0'; + buf->len = newlen; + + return 0; +} + +int reftable_buf_addstr(struct reftable_buf *buf, const char *s) +{ + return reftable_buf_add(buf, s, strlen(s)); +} + +char *reftable_buf_detach(struct reftable_buf *buf) +{ + char *result = buf->buf; + reftable_buf_init(buf); + return result; +} void put_be24(uint8_t *out, uint32_t i) { @@ -75,14 +210,14 @@ size_t names_length(const char **names) return p - names; } -void parse_names(char *buf, int size, char ***namesp) +char **parse_names(char *buf, int size) { char **names = NULL; size_t names_cap = 0; size_t names_len = 0; - char *p = buf; char *end = buf + size; + while (p < end) { char *next = strchr(p, '\n'); if (next && next < end) { @@ -91,15 +226,29 @@ void parse_names(char *buf, int size, char ***namesp) next = end; } if (p < next) { - REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap); - names[names_len++] = xstrdup(p); + char **names_grown = names; + REFTABLE_ALLOC_GROW(names_grown, names_len + 1, names_cap); + if (!names_grown) + goto err; + names = names_grown; + + names[names_len] = reftable_strdup(p); + if (!names[names_len++]) + goto err; } p = next + 1; } REFTABLE_REALLOC_ARRAY(names, names_len + 1); names[names_len] = NULL; - *namesp = names; + + return names; + +err: + for (size_t i = 0; i < names_len; i++) + reftable_free(names[i]); + reftable_free(names); + return NULL; } int names_equal(const char **a, const char **b) @@ -111,7 +260,7 @@ int names_equal(const char **a, const char **b) return a[i] == b[i]; } -int common_prefix_size(struct strbuf *a, struct strbuf *b) +int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b) { int p = 0; for (; p < a->len && p < b->len; p++) { @@ -121,3 +270,16 @@ int common_prefix_size(struct strbuf *a, struct strbuf *b) return p; } + +int hash_size(enum reftable_hash id) +{ + if (!id) + return REFTABLE_HASH_SIZE_SHA1; + switch (id) { + case REFTABLE_HASH_SHA1: + return REFTABLE_HASH_SIZE_SHA1; + case REFTABLE_HASH_SHA256: + return REFTABLE_HASH_SIZE_SHA256; + } + abort(); +} diff --git a/reftable/basics.h b/reftable/basics.h index c8fec68d4e..36beda2c25 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -14,6 +14,65 @@ https://developers.google.com/open-source/licenses/bsd */ #include "system.h" +#include "reftable-basics.h" + +struct reftable_buf { + size_t alloc; + size_t len; + char *buf; +}; +#define REFTABLE_BUF_INIT { 0 } + +/* + * Initialize the buffer such that it is ready for use. This is equivalent to + * using REFTABLE_BUF_INIT for stack-allocated variables. + */ +void reftable_buf_init(struct reftable_buf *buf); + +/* + * Release memory associated with the buffer. The buffer is reinitialized such + * that it can be reused for subsequent operations. + */ +void reftable_buf_release(struct reftable_buf *buf); + +/* + * Reset the buffer such that it is effectively empty, without releasing the + * memory that this structure holds on to. This is equivalent to calling + * `reftable_buf_setlen(buf, 0)`. + */ +void reftable_buf_reset(struct reftable_buf *buf); + +/* + * Trim the buffer to a shorter length by updating the `len` member and writing + * a NUL byte to `buf[len]`. Returns 0 on success, -1 when `len` points outside + * of the array. + */ +int reftable_buf_setlen(struct reftable_buf *buf, size_t len); + +/* + * Lexicographically compare the two buffers. Returns 0 when both buffers have + * the same contents, -1 when `a` is lexicographically smaller than `b`, and 1 + * otherwise. + */ +int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b); + +/* + * Append `len` bytes from `data` to the buffer. This function works with + * arbitrary byte sequences, including ones that contain embedded NUL + * characters. As such, we use `void *` as input type. Returns 0 on success, + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure. + */ +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len); + +/* Equivalent to `reftable_buf_add(buf, s, strlen(s))`. */ +int reftable_buf_addstr(struct reftable_buf *buf, const char *s); + +/* + * Detach the buffer from the structure such that the underlying memory is now + * owned by the caller. The buffer is reinitialized such that it can be reused + * for subsequent operations. + */ +char *reftable_buf_detach(struct reftable_buf *buf); /* Bigendian en/decoding of integers */ @@ -37,9 +96,12 @@ size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args); */ void free_names(char **a); -/* parse a newline separated list of names. `size` is the length of the buffer, - * without terminating '\0'. Empty names are discarded. */ -void parse_names(char *buf, int size, char ***namesp); +/* + * Parse a newline separated list of names. `size` is the length of the buffer, + * without terminating '\0'. Empty names are discarded. Returns a `NULL` + * pointer when allocations fail. + */ +char **parse_names(char *buf, int size); /* compares two NULL-terminated arrays of strings. */ int names_equal(const char **a, const char **b); @@ -53,6 +115,7 @@ void *reftable_malloc(size_t sz); void *reftable_realloc(void *p, size_t sz); void reftable_free(void *p); void *reftable_calloc(size_t nelem, size_t elsize); +char *reftable_strdup(const char *str); #define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc))) #define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x))) @@ -66,9 +129,33 @@ void *reftable_calloc(size_t nelem, size_t elsize); REFTABLE_REALLOC_ARRAY(x, alloc); \ } \ } while (0) +#define REFTABLE_FREE_AND_NULL(p) do { reftable_free(p); (p) = NULL; } while (0) + +#ifndef REFTABLE_ALLOW_BANNED_ALLOCATORS +# define REFTABLE_BANNED(func) use_reftable_##func##_instead +# undef malloc +# define malloc(sz) REFTABLE_BANNED(malloc) +# undef realloc +# define realloc(ptr, sz) REFTABLE_BANNED(realloc) +# undef free +# define free(ptr) REFTABLE_BANNED(free) +# undef calloc +# define calloc(nelem, elsize) REFTABLE_BANNED(calloc) +# undef strdup +# define strdup(str) REFTABLE_BANNED(strdup) +#endif /* Find the longest shared prefix size of `a` and `b` */ -struct strbuf; -int common_prefix_size(struct strbuf *a, struct strbuf *b); +int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); + +int hash_size(enum reftable_hash id); + +/* + * Format IDs that identify the hash function used by a reftable. Note that + * these constants end up on disk and thus mustn't change. The format IDs are + * "sha1" and "s256" in big endian, respectively. + */ +#define REFTABLE_FORMAT_ID_SHA1 ((uint32_t) 0x73686131) +#define REFTABLE_FORMAT_ID_SHA256 ((uint32_t) 0x73323536) #endif diff --git a/reftable/block.c b/reftable/block.c index 00030eee06..0198078485 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -38,9 +38,11 @@ int footer_size(int version) } static int block_writer_register_restart(struct block_writer *w, int n, - int is_restart, struct strbuf *key) + int is_restart, struct reftable_buf *key) { - int rlen = w->restart_len; + int rlen, err; + + rlen = w->restart_len; if (rlen >= MAX_RESTARTS) { is_restart = 0; } @@ -52,25 +54,30 @@ static int block_writer_register_restart(struct block_writer *w, int n, return -1; if (is_restart) { REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap); + if (!w->restarts) + return REFTABLE_OUT_OF_MEMORY_ERROR; w->restarts[w->restart_len++] = w->next; } w->next += n; - strbuf_reset(&w->last_key); - strbuf_addbuf(&w->last_key, key); + reftable_buf_reset(&w->last_key); + err = reftable_buf_add(&w->last_key, key->buf, key->len); + if (err < 0) + return err; + w->entries++; return 0; } -void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf, - uint32_t block_size, uint32_t header_off, int hash_size) +int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block, + uint32_t block_size, uint32_t header_off, int hash_size) { - bw->buf = buf; + bw->block = block; bw->hash_size = hash_size; bw->block_size = block_size; bw->header_off = header_off; - bw->buf[header_off] = typ; + bw->block[header_off] = typ; bw->next = header_off + 4; bw->restart_interval = 16; bw->entries = 0; @@ -78,13 +85,17 @@ void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf, bw->last_key.len = 0; if (!bw->zstream) { REFTABLE_CALLOC_ARRAY(bw->zstream, 1); + if (!bw->zstream) + return REFTABLE_OUT_OF_MEMORY_ERROR; deflateInit(bw->zstream, 9); } + + return 0; } uint8_t block_writer_type(struct block_writer *bw) { - return bw->buf[bw->header_off]; + return bw->block[bw->header_off]; } /* Adds the reftable_record to the block. Returns -1 if it does not fit, 0 on @@ -92,42 +103,45 @@ uint8_t block_writer_type(struct block_writer *bw) empty key. */ int block_writer_add(struct block_writer *w, struct reftable_record *rec) { - struct strbuf empty = STRBUF_INIT; - struct strbuf last = + struct reftable_buf empty = REFTABLE_BUF_INIT; + struct reftable_buf last = w->entries % w->restart_interval == 0 ? empty : w->last_key; struct string_view out = { - .buf = w->buf + w->next, + .buf = w->block + w->next, .len = w->block_size - w->next, }; - struct string_view start = out; - int is_restart = 0; - struct strbuf key = STRBUF_INIT; int n = 0; - int err = -1; + int err; + + err = reftable_record_key(rec, &w->scratch); + if (err < 0) + goto done; - reftable_record_key(rec, &key); - if (!key.len) { + if (!w->scratch.len) { err = REFTABLE_API_ERROR; goto done; } - n = reftable_encode_key(&is_restart, out, last, key, + n = reftable_encode_key(&is_restart, out, last, w->scratch, reftable_record_val_type(rec)); - if (n < 0) + if (n < 0) { + err = -1; goto done; + } string_view_consume(&out, n); n = reftable_record_encode(rec, out, w->hash_size); - if (n < 0) + if (n < 0) { + err = -1; goto done; + } string_view_consume(&out, n); err = block_writer_register_restart(w, start.len - out.len, is_restart, - &key); + &w->scratch); done: - strbuf_release(&key); return err; } @@ -135,13 +149,13 @@ int block_writer_finish(struct block_writer *w) { int i; for (i = 0; i < w->restart_len; i++) { - put_be24(w->buf + w->next, w->restarts[i]); + put_be24(w->block + w->next, w->restarts[i]); w->next += 3; } - put_be16(w->buf + w->next, w->restart_len); + put_be16(w->block + w->next, w->restart_len); w->next += 2; - put_be24(w->buf + 1 + w->header_off, w->next); + put_be24(w->block + 1 + w->header_off, w->next); /* * Log records are stored zlib-compressed. Note that the compression @@ -163,10 +177,14 @@ int block_writer_finish(struct block_writer *w) */ compressed_len = deflateBound(w->zstream, src_len); REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap); + if (!w->compressed) { + ret = REFTABLE_OUT_OF_MEMORY_ERROR; + return ret; + } w->zstream->next_out = w->compressed; w->zstream->avail_out = compressed_len; - w->zstream->next_in = w->buf + block_header_skip; + w->zstream->next_in = w->block + block_header_skip; w->zstream->avail_in = src_len; /* @@ -184,7 +202,7 @@ int block_writer_finish(struct block_writer *w) * adjust the `next` pointer to point right after the * compressed data. */ - memcpy(w->buf + block_header_skip, w->compressed, + memcpy(w->block + block_header_skip, w->compressed, w->zstream->total_out); w->next = w->zstream->total_out + block_header_skip; } @@ -219,12 +237,21 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, /* Log blocks specify the *uncompressed* size in their header. */ REFTABLE_ALLOC_GROW(br->uncompressed_data, sz, br->uncompressed_cap); + if (!br->uncompressed_data) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } /* Copy over the block header verbatim. It's not compressed. */ memcpy(br->uncompressed_data, block->data, block_header_skip); if (!br->zstream) { REFTABLE_CALLOC_ARRAY(br->zstream, 1); + if (!br->zstream) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + err = inflateInit(br->zstream); } else { err = inflateReset(br->zstream); @@ -306,7 +333,7 @@ uint8_t block_reader_type(const struct block_reader *r) return r->block.data[r->header_off]; } -int block_reader_first_key(const struct block_reader *br, struct strbuf *key) +int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key) { int off = br->header_off + 4, n; struct string_view in = { @@ -315,7 +342,7 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key) }; uint8_t extra = 0; - strbuf_reset(key); + reftable_buf_reset(key); n = reftable_decode_key(key, &extra, in); if (n < 0) @@ -336,13 +363,13 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) it->block = br->block.data; it->block_len = br->block_len; it->hash_size = br->hash_size; - strbuf_reset(&it->last_key); + reftable_buf_reset(&it->last_key); it->next_off = br->header_off + 4; } struct restart_needle_less_args { int error; - struct strbuf needle; + struct reftable_buf needle; const struct block_reader *reader; }; @@ -414,7 +441,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec) void block_iter_reset(struct block_iter *it) { - strbuf_reset(&it->last_key); + reftable_buf_reset(&it->last_key); it->next_off = 0; it->block = NULL; it->block_len = 0; @@ -423,12 +450,12 @@ void block_iter_reset(struct block_iter *it) void block_iter_close(struct block_iter *it) { - strbuf_release(&it->last_key); - strbuf_release(&it->scratch); + reftable_buf_release(&it->last_key); + reftable_buf_release(&it->scratch); } int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct strbuf *want) + struct reftable_buf *want) { struct restart_needle_less_args args = { .needle = *want, @@ -503,6 +530,10 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, goto done; } + err = reftable_record_key(&rec, &it->last_key); + if (err < 0) + goto done; + /* * Check whether the current key is greater or equal to the * sought-after key. In case it is greater we know that the @@ -517,8 +548,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, * to `last_key` now, and naturally all keys share a prefix * with themselves. */ - reftable_record_key(&rec, &it->last_key); - if (strbuf_cmp(&it->last_key, want) >= 0) { + if (reftable_buf_cmp(&it->last_key, want) >= 0) { it->next_off = prev_off; goto done; } @@ -532,10 +562,11 @@ done: void block_writer_release(struct block_writer *bw) { deflateEnd(bw->zstream); - FREE_AND_NULL(bw->zstream); - FREE_AND_NULL(bw->restarts); - FREE_AND_NULL(bw->compressed); - strbuf_release(&bw->last_key); + REFTABLE_FREE_AND_NULL(bw->zstream); + REFTABLE_FREE_AND_NULL(bw->restarts); + REFTABLE_FREE_AND_NULL(bw->compressed); + reftable_buf_release(&bw->scratch); + reftable_buf_release(&bw->last_key); /* the block is not owned. */ } diff --git a/reftable/block.h b/reftable/block.h index 1c8f25ee6e..0431e8591f 100644 --- a/reftable/block.h +++ b/reftable/block.h @@ -22,7 +22,7 @@ struct block_writer { unsigned char *compressed; size_t compressed_cap; - uint8_t *buf; + uint8_t *block; uint32_t block_size; /* Offset of the global header. Nonzero in the first block only. */ @@ -38,15 +38,17 @@ struct block_writer { uint32_t restart_len; uint32_t restart_cap; - struct strbuf last_key; + struct reftable_buf last_key; + /* Scratch buffer used to avoid allocations. */ + struct reftable_buf scratch; int entries; }; /* - * initializes the blockwriter to write `typ` entries, using `buf` as temporary - * storage. `buf` is not owned by the block_writer. */ -void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf, - uint32_t block_size, uint32_t header_off, int hash_size); + * initializes the blockwriter to write `typ` entries, using `block` as temporary + * storage. `block` is not owned by the block_writer. */ +int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block, + uint32_t block_size, uint32_t header_off, int hash_size); /* returns the block type (eg. 'r' for ref records. */ uint8_t block_writer_type(struct block_writer *bw); @@ -98,7 +100,7 @@ void block_reader_release(struct block_reader *br); uint8_t block_reader_type(const struct block_reader *r); /* Decodes the first key in the block */ -int block_reader_first_key(const struct block_reader *br, struct strbuf *key); +int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key); /* Iterate over entries in a block */ struct block_iter { @@ -109,13 +111,13 @@ struct block_iter { int hash_size; /* key for last entry we read. */ - struct strbuf last_key; - struct strbuf scratch; + struct reftable_buf last_key; + struct reftable_buf scratch; }; #define BLOCK_ITER_INIT { \ - .last_key = STRBUF_INIT, \ - .scratch = STRBUF_INIT, \ + .last_key = REFTABLE_BUF_INIT, \ + .scratch = REFTABLE_BUF_INIT, \ } /* Position `it` at start of the block */ @@ -123,7 +125,7 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) /* Position `it` to the `want` key in the block */ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct strbuf *want); + struct reftable_buf *want); /* return < 0 for error, 0 for OK, > 0 for EOF. */ int block_iter_next(struct block_iter *it, struct reftable_record *rec); diff --git a/reftable/block_test.c b/reftable/block_test.c deleted file mode 100644 index 90aecd5a7c..0000000000 --- a/reftable/block_test.c +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "block.h" - -#include "system.h" -#include "blocksource.h" -#include "basics.h" -#include "constants.h" -#include "record.h" -#include "test_framework.h" -#include "reftable-tests.h" - -static void test_block_read_write(void) -{ - const int header_off = 21; /* random */ - char *names[30]; - const int N = ARRAY_SIZE(names); - const int block_size = 1024; - struct reftable_block block = { NULL }; - struct block_writer bw = { - .last_key = STRBUF_INIT, - }; - struct reftable_record rec = { - .type = BLOCK_TYPE_REF, - }; - int i = 0; - int n; - struct block_reader br = { 0 }; - struct block_iter it = BLOCK_ITER_INIT; - int j = 0; - struct strbuf want = STRBUF_INIT; - - REFTABLE_CALLOC_ARRAY(block.data, block_size); - block.len = block_size; - block.source = malloc_block_source(); - block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, - header_off, hash_size(GIT_SHA1_FORMAT_ID)); - - rec.u.ref.refname = (char *) ""; - rec.u.ref.value_type = REFTABLE_REF_DELETION; - n = block_writer_add(&bw, &rec); - EXPECT(n == REFTABLE_API_ERROR); - - for (i = 0; i < N; i++) { - char name[100]; - snprintf(name, sizeof(name), "branch%02d", i); - - rec.u.ref.refname = name; - rec.u.ref.value_type = REFTABLE_REF_VAL1; - memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ); - - names[i] = xstrdup(name); - n = block_writer_add(&bw, &rec); - rec.u.ref.refname = NULL; - rec.u.ref.value_type = REFTABLE_REF_DELETION; - EXPECT(n == 0); - } - - n = block_writer_finish(&bw); - EXPECT(n > 0); - - block_writer_release(&bw); - - block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); - - block_iter_seek_start(&it, &br); - - while (1) { - int r = block_iter_next(&it, &rec); - EXPECT(r >= 0); - if (r > 0) { - break; - } - EXPECT_STREQ(names[j], rec.u.ref.refname); - j++; - } - - reftable_record_release(&rec); - block_iter_close(&it); - - for (i = 0; i < N; i++) { - struct block_iter it = BLOCK_ITER_INIT; - strbuf_reset(&want); - strbuf_addstr(&want, names[i]); - - n = block_iter_seek_key(&it, &br, &want); - EXPECT(n == 0); - - n = block_iter_next(&it, &rec); - EXPECT(n == 0); - - EXPECT_STREQ(names[i], rec.u.ref.refname); - - want.len--; - n = block_iter_seek_key(&it, &br, &want); - EXPECT(n == 0); - - n = block_iter_next(&it, &rec); - EXPECT(n == 0); - EXPECT_STREQ(names[10 * (i / 10)], rec.u.ref.refname); - - block_iter_close(&it); - } - - reftable_record_release(&rec); - reftable_block_done(&br.block); - strbuf_release(&want); - for (i = 0; i < N; i++) { - reftable_free(names[i]); - } -} - -int block_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_block_read_write); - return 0; -} diff --git a/reftable/blocksource.c b/reftable/blocksource.c index eeed254ba9..52e0915a67 100644 --- a/reftable/blocksource.c +++ b/reftable/blocksource.c @@ -13,68 +13,50 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-blocksource.h" #include "reftable-error.h" -static void strbuf_return_block(void *b, struct reftable_block *dest) +static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest) { if (dest->len) memset(dest->data, 0xff, dest->len); reftable_free(dest->data); } -static void strbuf_close(void *b) +static void reftable_buf_close(void *b UNUSED) { } -static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off, - uint32_t size) +static int reftable_buf_read_block(void *v, struct reftable_block *dest, + uint64_t off, uint32_t size) { - struct strbuf *b = v; + struct reftable_buf *b = v; assert(off + size <= b->len); REFTABLE_CALLOC_ARRAY(dest->data, size); + if (!dest->data) + return -1; memcpy(dest->data, b->buf + off, size); dest->len = size; return size; } -static uint64_t strbuf_size(void *b) +static uint64_t reftable_buf_size(void *b) { - return ((struct strbuf *)b)->len; + return ((struct reftable_buf *)b)->len; } -static struct reftable_block_source_vtable strbuf_vtable = { - .size = &strbuf_size, - .read_block = &strbuf_read_block, - .return_block = &strbuf_return_block, - .close = &strbuf_close, +static struct reftable_block_source_vtable reftable_buf_vtable = { + .size = &reftable_buf_size, + .read_block = &reftable_buf_read_block, + .return_block = &reftable_buf_return_block, + .close = &reftable_buf_close, }; -void block_source_from_strbuf(struct reftable_block_source *bs, - struct strbuf *buf) +void block_source_from_buf(struct reftable_block_source *bs, + struct reftable_buf *buf) { assert(!bs->ops); - bs->ops = &strbuf_vtable; + bs->ops = &reftable_buf_vtable; bs->arg = buf; } -static void malloc_return_block(void *b, struct reftable_block *dest) -{ - if (dest->len) - memset(dest->data, 0xff, dest->len); - reftable_free(dest->data); -} - -static struct reftable_block_source_vtable malloc_vtable = { - .return_block = &malloc_return_block, -}; - -static struct reftable_block_source malloc_block_source_instance = { - .ops = &malloc_vtable, -}; - -struct reftable_block_source malloc_block_source(void) -{ - return malloc_block_source_instance; -} - struct file_block_source { uint64_t size; unsigned char *data; @@ -85,7 +67,7 @@ static uint64_t file_size(void *b) return ((struct file_block_source *)b)->size; } -static void file_return_block(void *b, struct reftable_block *dest) +static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED) { } @@ -118,27 +100,40 @@ int reftable_block_source_from_file(struct reftable_block_source *bs, { struct file_block_source *p; struct stat st; - int fd; + int fd, err; fd = open(name, O_RDONLY); if (fd < 0) { if (errno == ENOENT) return REFTABLE_NOT_EXIST_ERROR; - return -1; + err = -1; + goto out; } if (fstat(fd, &st) < 0) { - close(fd); - return REFTABLE_IO_ERROR; + err = REFTABLE_IO_ERROR; + goto out; } REFTABLE_CALLOC_ARRAY(p, 1); + if (!p) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + p->size = st.st_size; p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); assert(!bs->ops); bs->ops = &file_vtable; bs->arg = p; + + err = 0; + +out: + if (fd >= 0) + close(fd); + if (err < 0) + reftable_free(p); return 0; } diff --git a/reftable/blocksource.h b/reftable/blocksource.h index 072e2727ad..a84a3ccd89 100644 --- a/reftable/blocksource.h +++ b/reftable/blocksource.h @@ -12,11 +12,10 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" struct reftable_block_source; +struct reftable_buf; /* Create an in-memory block source for reading reftables */ -void block_source_from_strbuf(struct reftable_block_source *bs, - struct strbuf *buf); - -struct reftable_block_source malloc_block_source(void); +void block_source_from_buf(struct reftable_block_source *bs, + struct reftable_buf *buf); #endif diff --git a/reftable/dump.c b/reftable/dump.c deleted file mode 100644 index dd65d9e8bb..0000000000 --- a/reftable/dump.c +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "git-compat-util.h" -#include "hash.h" - -#include "reftable-blocksource.h" -#include "reftable-error.h" -#include "reftable-record.h" -#include "reftable-tests.h" -#include "reftable-writer.h" -#include "reftable-iterator.h" -#include "reftable-reader.h" -#include "reftable-stack.h" - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -static int compact_stack(const char *stackdir) -{ - struct reftable_stack *stack = NULL; - struct reftable_write_options opts = { 0 }; - - int err = reftable_new_stack(&stack, stackdir, &opts); - if (err < 0) - goto done; - - err = reftable_stack_compact_all(stack, NULL); - if (err < 0) - goto done; -done: - if (stack) { - reftable_stack_destroy(stack); - } - return err; -} - -static void print_help(void) -{ - printf("usage: dump [-cst] arg\n\n" - "options: \n" - " -c compact\n" - " -b dump blocks\n" - " -t dump table\n" - " -s dump stack\n" - " -6 sha256 hash format\n" - " -h this help\n" - "\n"); -} - -int reftable_dump_main(int argc, char *const *argv) -{ - int err = 0; - int opt_dump_blocks = 0; - int opt_dump_table = 0; - int opt_dump_stack = 0; - int opt_compact = 0; - uint32_t opt_hash_id = GIT_SHA1_FORMAT_ID; - const char *arg = NULL, *argv0 = argv[0]; - - for (; argc > 1; argv++, argc--) - if (*argv[1] != '-') - break; - else if (!strcmp("-b", argv[1])) - opt_dump_blocks = 1; - else if (!strcmp("-t", argv[1])) - opt_dump_table = 1; - else if (!strcmp("-6", argv[1])) - opt_hash_id = GIT_SHA256_FORMAT_ID; - else if (!strcmp("-s", argv[1])) - opt_dump_stack = 1; - else if (!strcmp("-c", argv[1])) - opt_compact = 1; - else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) { - print_help(); - return 2; - } - - if (argc != 2) { - fprintf(stderr, "need argument\n"); - print_help(); - return 2; - } - - arg = argv[1]; - - if (opt_dump_blocks) { - err = reftable_reader_print_blocks(arg); - } else if (opt_dump_table) { - err = reftable_reader_print_file(arg); - } else if (opt_dump_stack) { - err = reftable_stack_print_directory(arg, opt_hash_id); - } else if (opt_compact) { - err = compact_stack(arg); - } - - if (err < 0) { - fprintf(stderr, "%s: %s: %s\n", argv0, arg, - reftable_error_str(err)); - return 1; - } - return 0; -} diff --git a/reftable/error.c b/reftable/error.c index a25f28a43e..660d029617 100644 --- a/reftable/error.c +++ b/reftable/error.c @@ -35,6 +35,8 @@ const char *reftable_error_str(int err) return "entry too large"; case REFTABLE_OUTDATED_ERROR: return "data concurrently modified"; + case REFTABLE_OUT_OF_MEMORY_ERROR: + return "out of memory"; case -1: return "general error"; default: diff --git a/reftable/generic.c b/reftable/generic.c deleted file mode 100644 index 28ae26145e..0000000000 --- a/reftable/generic.c +++ /dev/null @@ -1,229 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "constants.h" -#include "record.h" -#include "generic.h" -#include "reftable-iterator.h" -#include "reftable-generic.h" - -void table_init_iter(struct reftable_table *tab, - struct reftable_iterator *it, - uint8_t typ) -{ - - tab->ops->init_iter(tab->table_arg, it, typ); -} - -void reftable_table_init_ref_iter(struct reftable_table *tab, - struct reftable_iterator *it) -{ - table_init_iter(tab, it, BLOCK_TYPE_REF); -} - -void reftable_table_init_log_iter(struct reftable_table *tab, - struct reftable_iterator *it) -{ - table_init_iter(tab, it, BLOCK_TYPE_LOG); -} - -int reftable_iterator_seek_ref(struct reftable_iterator *it, - const char *name) -{ - struct reftable_record want = { - .type = BLOCK_TYPE_REF, - .u.ref = { - .refname = (char *)name, - }, - }; - return it->ops->seek(it->iter_arg, &want); -} - -int reftable_iterator_seek_log_at(struct reftable_iterator *it, - const char *name, uint64_t update_index) -{ - struct reftable_record want = { - .type = BLOCK_TYPE_LOG, - .u.log = { - .refname = (char *)name, - .update_index = update_index, - }, - }; - return it->ops->seek(it->iter_arg, &want); -} - -int reftable_iterator_seek_log(struct reftable_iterator *it, - const char *name) -{ - return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0)); -} - -int reftable_table_read_ref(struct reftable_table *tab, const char *name, - struct reftable_ref_record *ref) -{ - struct reftable_iterator it = { NULL }; - int err; - - reftable_table_init_ref_iter(tab, &it); - - err = reftable_iterator_seek_ref(&it, name); - if (err) - goto done; - - err = reftable_iterator_next_ref(&it, ref); - if (err) - goto done; - - if (strcmp(ref->refname, name) || - reftable_ref_record_is_deletion(ref)) { - reftable_ref_record_release(ref); - err = 1; - goto done; - } - -done: - reftable_iterator_destroy(&it); - return err; -} - -int reftable_table_print(struct reftable_table *tab) { - struct reftable_iterator it = { NULL }; - struct reftable_ref_record ref = { NULL }; - struct reftable_log_record log = { NULL }; - uint32_t hash_id = reftable_table_hash_id(tab); - int err; - - reftable_table_init_ref_iter(tab, &it); - - err = reftable_iterator_seek_ref(&it, ""); - if (err < 0) - return err; - - while (1) { - err = reftable_iterator_next_ref(&it, &ref); - if (err > 0) { - break; - } - if (err < 0) { - return err; - } - reftable_ref_record_print(&ref, hash_id); - } - reftable_iterator_destroy(&it); - reftable_ref_record_release(&ref); - - reftable_table_init_log_iter(tab, &it); - - err = reftable_iterator_seek_log(&it, ""); - if (err < 0) - return err; - - while (1) { - err = reftable_iterator_next_log(&it, &log); - if (err > 0) { - break; - } - if (err < 0) { - return err; - } - reftable_log_record_print(&log, hash_id); - } - reftable_iterator_destroy(&it); - reftable_log_record_release(&log); - return 0; -} - -uint64_t reftable_table_max_update_index(struct reftable_table *tab) -{ - return tab->ops->max_update_index(tab->table_arg); -} - -uint64_t reftable_table_min_update_index(struct reftable_table *tab) -{ - return tab->ops->min_update_index(tab->table_arg); -} - -uint32_t reftable_table_hash_id(struct reftable_table *tab) -{ - return tab->ops->hash_id(tab->table_arg); -} - -void reftable_iterator_destroy(struct reftable_iterator *it) -{ - if (!it->ops) { - return; - } - it->ops->close(it->iter_arg); - it->ops = NULL; - FREE_AND_NULL(it->iter_arg); -} - -int reftable_iterator_next_ref(struct reftable_iterator *it, - struct reftable_ref_record *ref) -{ - struct reftable_record rec = { - .type = BLOCK_TYPE_REF, - .u = { - .ref = *ref - }, - }; - int err = iterator_next(it, &rec); - *ref = rec.u.ref; - return err; -} - -int reftable_iterator_next_log(struct reftable_iterator *it, - struct reftable_log_record *log) -{ - struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, - .u = { - .log = *log, - }, - }; - int err = iterator_next(it, &rec); - *log = rec.u.log; - return err; -} - -int iterator_seek(struct reftable_iterator *it, struct reftable_record *want) -{ - return it->ops->seek(it->iter_arg, want); -} - -int iterator_next(struct reftable_iterator *it, struct reftable_record *rec) -{ - return it->ops->next(it->iter_arg, rec); -} - -static int empty_iterator_seek(void *arg, struct reftable_record *want) -{ - return 0; -} - -static int empty_iterator_next(void *arg, struct reftable_record *rec) -{ - return 1; -} - -static void empty_iterator_close(void *arg) -{ -} - -static struct reftable_iterator_vtable empty_vtable = { - .seek = &empty_iterator_seek, - .next = &empty_iterator_next, - .close = &empty_iterator_close, -}; - -void iterator_set_empty(struct reftable_iterator *it) -{ - assert(!it->ops); - it->iter_arg = NULL; - it->ops = &empty_vtable; -} diff --git a/reftable/generic.h b/reftable/generic.h deleted file mode 100644 index 8341fa570e..0000000000 --- a/reftable/generic.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef GENERIC_H -#define GENERIC_H - -#include "record.h" -#include "reftable-generic.h" - -/* generic interface to reftables */ -struct reftable_table_vtable { - void (*init_iter)(void *tab, struct reftable_iterator *it, uint8_t typ); - uint32_t (*hash_id)(void *tab); - uint64_t (*min_update_index)(void *tab); - uint64_t (*max_update_index)(void *tab); -}; - -void table_init_iter(struct reftable_table *tab, - struct reftable_iterator *it, - uint8_t typ); - -struct reftable_iterator_vtable { - int (*seek)(void *iter_arg, struct reftable_record *want); - int (*next)(void *iter_arg, struct reftable_record *rec); - void (*close)(void *iter_arg); -}; - -void iterator_set_empty(struct reftable_iterator *it); -int iterator_seek(struct reftable_iterator *it, struct reftable_record *want); -int iterator_next(struct reftable_iterator *it, struct reftable_record *rec); - -#endif diff --git a/reftable/iter.c b/reftable/iter.c index fddea31e51..86e801ca9f 100644 --- a/reftable/iter.c +++ b/reftable/iter.c @@ -11,15 +11,51 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" #include "block.h" -#include "generic.h" #include "constants.h" #include "reader.h" #include "reftable-error.h" +int iterator_seek(struct reftable_iterator *it, struct reftable_record *want) +{ + return it->ops->seek(it->iter_arg, want); +} + +int iterator_next(struct reftable_iterator *it, struct reftable_record *rec) +{ + return it->ops->next(it->iter_arg, rec); +} + +static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED) +{ + return 0; +} + +static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED) +{ + return 1; +} + +static void empty_iterator_close(void *arg UNUSED) +{ +} + +static struct reftable_iterator_vtable empty_vtable = { + .seek = &empty_iterator_seek, + .next = &empty_iterator_next, + .close = &empty_iterator_close, +}; + +void iterator_set_empty(struct reftable_iterator *it) +{ + assert(!it->ops); + it->iter_arg = NULL; + it->ops = &empty_vtable; +} + static void filtering_ref_iterator_close(void *iter_arg) { struct filtering_ref_iterator *fri = iter_arg; - strbuf_release(&fri->oid); + reftable_buf_release(&fri->oid); reftable_iterator_destroy(&fri->it); } @@ -42,26 +78,6 @@ static int filtering_ref_iterator_next(void *iter_arg, break; } - if (fri->double_check) { - struct reftable_iterator it = { NULL }; - - reftable_table_init_ref_iter(&fri->tab, &it); - - err = reftable_iterator_seek_ref(&it, ref->refname); - if (err == 0) - err = reftable_iterator_next_ref(&it, ref); - - reftable_iterator_destroy(&it); - - if (err < 0) { - break; - } - - if (err > 0) { - continue; - } - } - if (ref->value_type == REFTABLE_REF_VAL2 && (!memcmp(fri->oid.buf, ref->value.val2.target_value, fri->oid.len) || @@ -99,7 +115,7 @@ static void indexed_table_ref_iter_close(void *p) block_iter_close(&it->cur); reftable_block_done(&it->block_reader.block); reftable_free(it->offsets); - strbuf_release(&it->oid); + reftable_buf_release(&it->oid); } static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) @@ -127,7 +143,8 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) return 0; } -static int indexed_table_ref_iter_seek(void *p, struct reftable_record *want) +static int indexed_table_ref_iter_seek(void *p UNUSED, + struct reftable_record *want UNUSED) { BUG("seeking indexed table is not supported"); return -1; @@ -164,26 +181,41 @@ static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec) } } -int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest, +int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, struct reftable_reader *r, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len) { struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT; - struct indexed_table_ref_iter *itr = reftable_calloc(1, sizeof(*itr)); + struct indexed_table_ref_iter *itr; int err = 0; + itr = reftable_calloc(1, sizeof(*itr)); + if (!itr) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + *itr = empty; itr->r = r; - strbuf_add(&itr->oid, oid, oid_len); + + err = reftable_buf_add(&itr->oid, oid, oid_len); + if (err < 0) + goto out; itr->offsets = offsets; itr->offset_len = offset_len; err = indexed_table_ref_iter_next_block(itr); + if (err < 0) + goto out; + + *dest = itr; + err = 0; + +out: if (err < 0) { + *dest = NULL; reftable_free(itr); - } else { - *dest = itr; } return err; } @@ -201,3 +233,71 @@ void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it, it->iter_arg = itr; it->ops = &indexed_table_ref_iter_vtable; } + +void reftable_iterator_destroy(struct reftable_iterator *it) +{ + if (!it->ops) + return; + it->ops->close(it->iter_arg); + it->ops = NULL; + REFTABLE_FREE_AND_NULL(it->iter_arg); +} + +int reftable_iterator_seek_ref(struct reftable_iterator *it, + const char *name) +{ + struct reftable_record want = { + .type = BLOCK_TYPE_REF, + .u.ref = { + .refname = (char *)name, + }, + }; + return it->ops->seek(it->iter_arg, &want); +} + +int reftable_iterator_next_ref(struct reftable_iterator *it, + struct reftable_ref_record *ref) +{ + struct reftable_record rec = { + .type = BLOCK_TYPE_REF, + .u = { + .ref = *ref + }, + }; + int err = iterator_next(it, &rec); + *ref = rec.u.ref; + return err; +} + +int reftable_iterator_seek_log_at(struct reftable_iterator *it, + const char *name, uint64_t update_index) +{ + struct reftable_record want = { + .type = BLOCK_TYPE_LOG, + .u.log = { + .refname = (char *)name, + .update_index = update_index, + }, + }; + return it->ops->seek(it->iter_arg, &want); +} + +int reftable_iterator_seek_log(struct reftable_iterator *it, + const char *name) +{ + return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0)); +} + +int reftable_iterator_next_log(struct reftable_iterator *it, + struct reftable_log_record *log) +{ + struct reftable_record rec = { + .type = BLOCK_TYPE_LOG, + .u = { + .log = *log, + }, + }; + int err = iterator_next(it, &rec); + *log = rec.u.log; + return err; +} diff --git a/reftable/iter.h b/reftable/iter.h index 537431baba..40f98893b8 100644 --- a/reftable/iter.h +++ b/reftable/iter.h @@ -14,18 +14,42 @@ https://developers.google.com/open-source/licenses/bsd #include "record.h" #include "reftable-iterator.h" -#include "reftable-generic.h" + +/* + * The virtual function table for implementing generic reftable iterators. + */ +struct reftable_iterator_vtable { + int (*seek)(void *iter_arg, struct reftable_record *want); + int (*next)(void *iter_arg, struct reftable_record *rec); + void (*close)(void *iter_arg); +}; + +/* + * Position the iterator at the wanted record such that a call to + * `iterator_next()` would return that record, if it exists. + */ +int iterator_seek(struct reftable_iterator *it, struct reftable_record *want); + +/* + * Yield the next record and advance the iterator. Returns <0 on error, 0 when + * a record was yielded, and >0 when the iterator hit an error. + */ +int iterator_next(struct reftable_iterator *it, struct reftable_record *rec); + +/* + * Set up the iterator such that it behaves the same as an iterator with no + * entries. + */ +void iterator_set_empty(struct reftable_iterator *it); /* iterator that produces only ref records that point to `oid` */ struct filtering_ref_iterator { - int double_check; - struct reftable_table tab; - struct strbuf oid; + struct reftable_buf oid; struct reftable_iterator it; }; #define FILTERING_REF_ITERATOR_INIT \ { \ - .oid = STRBUF_INIT \ + .oid = REFTABLE_BUF_INIT \ } void iterator_from_filtering_ref_iterator(struct reftable_iterator *, @@ -36,7 +60,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *, */ struct indexed_table_ref_iter { struct reftable_reader *r; - struct strbuf oid; + struct reftable_buf oid; /* mutable */ uint64_t *offsets; @@ -51,14 +75,14 @@ struct indexed_table_ref_iter { #define INDEXED_TABLE_REF_ITER_INIT { \ .cur = BLOCK_ITER_INIT, \ - .oid = STRBUF_INIT, \ + .oid = REFTABLE_BUF_INIT, \ } void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it, struct indexed_table_ref_iter *itr); /* Takes ownership of `offsets` */ -int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest, +int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, struct reftable_reader *r, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len); diff --git a/reftable/merged.c b/reftable/merged.c index 6adce44f4b..bb0836e344 100644 --- a/reftable/merged.c +++ b/reftable/merged.c @@ -11,8 +11,8 @@ https://developers.google.com/open-source/licenses/bsd #include "constants.h" #include "iter.h" #include "pq.h" +#include "reader.h" #include "record.h" -#include "generic.h" #include "reftable-merged.h" #include "reftable-error.h" #include "system.h" @@ -25,33 +25,17 @@ struct merged_subiter { struct merged_iter { struct merged_subiter *subiters; struct merged_iter_pqueue pq; - size_t stack_len; + size_t subiters_len; int suppress_deletions; ssize_t advance_index; }; -static void merged_iter_init(struct merged_iter *mi, - struct reftable_merged_table *mt, - uint8_t typ) -{ - memset(mi, 0, sizeof(*mi)); - mi->advance_index = -1; - mi->suppress_deletions = mt->suppress_deletions; - - REFTABLE_CALLOC_ARRAY(mi->subiters, mt->stack_len); - for (size_t i = 0; i < mt->stack_len; i++) { - reftable_record_init(&mi->subiters[i].rec, typ); - table_init_iter(&mt->stack[i], &mi->subiters[i].iter, typ); - } - mi->stack_len = mt->stack_len; -} - static void merged_iter_close(void *p) { struct merged_iter *mi = p; merged_iter_pqueue_release(&mi->pq); - for (size_t i = 0; i < mi->stack_len; i++) { + for (size_t i = 0; i < mi->subiters_len; i++) { reftable_iterator_destroy(&mi->subiters[i].iter); reftable_record_release(&mi->subiters[i].rec); } @@ -70,7 +54,10 @@ static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx) if (err) return err; - merged_iter_pqueue_add(&mi->pq, &e); + err = merged_iter_pqueue_add(&mi->pq, &e); + if (err) + return err; + return 0; } @@ -79,8 +66,10 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want int err; mi->advance_index = -1; + while (!merged_iter_pqueue_is_empty(mi->pq)) + merged_iter_pqueue_remove(&mi->pq); - for (size_t i = 0; i < mi->stack_len; i++) { + for (size_t i = 0; i < mi->subiters_len; i++) { err = iterator_seek(&mi->subiters[i].iter, want); if (err < 0) return err; @@ -192,19 +181,19 @@ static void iterator_from_merged_iter(struct reftable_iterator *it, it->ops = &merged_iter_vtable; } -int reftable_new_merged_table(struct reftable_merged_table **dest, - struct reftable_table *stack, size_t n, - uint32_t hash_id) +int reftable_merged_table_new(struct reftable_merged_table **dest, + struct reftable_reader **readers, size_t n, + enum reftable_hash hash_id) { struct reftable_merged_table *m = NULL; uint64_t last_max = 0; uint64_t first_min = 0; for (size_t i = 0; i < n; i++) { - uint64_t min = reftable_table_min_update_index(&stack[i]); - uint64_t max = reftable_table_max_update_index(&stack[i]); + uint64_t min = reftable_reader_min_update_index(readers[i]); + uint64_t max = reftable_reader_max_update_index(readers[i]); - if (reftable_table_hash_id(&stack[i]) != hash_id) { + if (reftable_reader_hash_id(readers[i]) != hash_id) { return REFTABLE_FORMAT_ERROR; } if (i == 0 || min < first_min) { @@ -216,8 +205,11 @@ int reftable_new_merged_table(struct reftable_merged_table **dest, } REFTABLE_CALLOC_ARRAY(m, 1); - m->stack = stack; - m->stack_len = n; + if (!m) + return REFTABLE_OUT_OF_MEMORY_ERROR; + + m->readers = readers; + m->readers_len = n; m->min = first_min; m->max = last_max; m->hash_id = hash_id; @@ -229,7 +221,6 @@ void reftable_merged_table_free(struct reftable_merged_table *mt) { if (!mt) return; - FREE_AND_NULL(mt->stack); reftable_free(mt); } @@ -245,53 +236,66 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt) return mt->min; } -void merged_table_init_iter(struct reftable_merged_table *mt, - struct reftable_iterator *it, - uint8_t typ) +int merged_table_init_iter(struct reftable_merged_table *mt, + struct reftable_iterator *it, + uint8_t typ) { - struct merged_iter *mi = reftable_malloc(sizeof(*mi)); - merged_iter_init(mi, mt, typ); - iterator_from_merged_iter(it, mi); -} + struct merged_subiter *subiters; + struct merged_iter *mi = NULL; + int ret; -uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt) -{ - return mt->hash_id; -} + REFTABLE_CALLOC_ARRAY(subiters, mt->readers_len); + if (!subiters) { + ret = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } -static void reftable_merged_table_init_iter_void(void *tab, - struct reftable_iterator *it, - uint8_t typ) -{ - merged_table_init_iter(tab, it, typ); -} + for (size_t i = 0; i < mt->readers_len; i++) { + reftable_record_init(&subiters[i].rec, typ); + ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ); + if (ret < 0) + goto out; + } -static uint32_t reftable_merged_table_hash_id_void(void *tab) -{ - return reftable_merged_table_hash_id(tab); + REFTABLE_CALLOC_ARRAY(mi, 1); + if (!mi) { + ret = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + mi->advance_index = -1; + mi->suppress_deletions = mt->suppress_deletions; + mi->subiters = subiters; + mi->subiters_len = mt->readers_len; + + iterator_from_merged_iter(it, mi); + ret = 0; + +out: + if (ret < 0) { + for (size_t i = 0; subiters && i < mt->readers_len; i++) { + reftable_iterator_destroy(&subiters[i].iter); + reftable_record_release(&subiters[i].rec); + } + reftable_free(subiters); + reftable_free(mi); + } + + return ret; } -static uint64_t reftable_merged_table_min_update_index_void(void *tab) +int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, + struct reftable_iterator *it) { - return reftable_merged_table_min_update_index(tab); + return merged_table_init_iter(mt, it, BLOCK_TYPE_REF); } -static uint64_t reftable_merged_table_max_update_index_void(void *tab) +int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, + struct reftable_iterator *it) { - return reftable_merged_table_max_update_index(tab); + return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); } -static struct reftable_table_vtable merged_table_vtable = { - .init_iter = reftable_merged_table_init_iter_void, - .hash_id = reftable_merged_table_hash_id_void, - .min_update_index = reftable_merged_table_min_update_index_void, - .max_update_index = reftable_merged_table_max_update_index_void, -}; - -void reftable_table_from_merged_table(struct reftable_table *tab, - struct reftable_merged_table *merged) +enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *mt) { - assert(!tab->ops); - tab->ops = &merged_table_vtable; - tab->table_arg = merged; + return mt->hash_id; } diff --git a/reftable/merged.h b/reftable/merged.h index 2efe571da6..0b7d939e92 100644 --- a/reftable/merged.h +++ b/reftable/merged.h @@ -10,11 +10,12 @@ https://developers.google.com/open-source/licenses/bsd #define MERGED_H #include "system.h" +#include "reftable-basics.h" struct reftable_merged_table { - struct reftable_table *stack; - size_t stack_len; - uint32_t hash_id; + struct reftable_reader **readers; + size_t readers_len; + enum reftable_hash hash_id; /* If unset, produce deletions. This is useful for compaction. For the * full stack, deletions should be produced. */ @@ -26,8 +27,8 @@ struct reftable_merged_table { struct reftable_iterator; -void merged_table_init_iter(struct reftable_merged_table *mt, - struct reftable_iterator *it, - uint8_t typ); +int merged_table_init_iter(struct reftable_merged_table *mt, + struct reftable_iterator *it, + uint8_t typ); #endif diff --git a/reftable/merged_test.c b/reftable/merged_test.c deleted file mode 100644 index a9d6661c13..0000000000 --- a/reftable/merged_test.c +++ /dev/null @@ -1,461 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "merged.h" - -#include "system.h" - -#include "basics.h" -#include "blocksource.h" -#include "constants.h" -#include "reader.h" -#include "record.h" -#include "test_framework.h" -#include "reftable-merged.h" -#include "reftable-tests.h" -#include "reftable-generic.h" -#include "reftable-writer.h" - -static void write_test_table(struct strbuf *buf, - struct reftable_ref_record refs[], int n) -{ - uint64_t min = 0xffffffff; - uint64_t max = 0; - int i = 0; - int err; - - struct reftable_write_options opts = { - .block_size = 256, - }; - struct reftable_writer *w = NULL; - for (i = 0; i < n; i++) { - uint64_t ui = refs[i].update_index; - if (ui > max) { - max = ui; - } - if (ui < min) { - min = ui; - } - } - - w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts); - reftable_writer_set_limits(w, min, max); - - for (i = 0; i < n; i++) { - uint64_t before = refs[i].update_index; - int n = reftable_writer_add_ref(w, &refs[i]); - EXPECT(n == 0); - EXPECT(before == refs[i].update_index); - } - - err = reftable_writer_close(w); - EXPECT_ERR(err); - - reftable_writer_free(w); -} - -static void write_test_log_table(struct strbuf *buf, - struct reftable_log_record logs[], int n, - uint64_t update_index) -{ - int i = 0; - int err; - - struct reftable_write_options opts = { - .block_size = 256, - .exact_log_message = 1, - }; - struct reftable_writer *w = NULL; - w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts); - reftable_writer_set_limits(w, update_index, update_index); - - for (i = 0; i < n; i++) { - int err = reftable_writer_add_log(w, &logs[i]); - EXPECT_ERR(err); - } - - err = reftable_writer_close(w); - EXPECT_ERR(err); - - reftable_writer_free(w); -} - -static struct reftable_merged_table * -merged_table_from_records(struct reftable_ref_record **refs, - struct reftable_block_source **source, - struct reftable_reader ***readers, int *sizes, - struct strbuf *buf, size_t n) -{ - struct reftable_merged_table *mt = NULL; - struct reftable_table *tabs; - int err; - - REFTABLE_CALLOC_ARRAY(tabs, n); - REFTABLE_CALLOC_ARRAY(*readers, n); - REFTABLE_CALLOC_ARRAY(*source, n); - - for (size_t i = 0; i < n; i++) { - write_test_table(&buf[i], refs[i], sizes[i]); - block_source_from_strbuf(&(*source)[i], &buf[i]); - - err = reftable_new_reader(&(*readers)[i], &(*source)[i], - "name"); - EXPECT_ERR(err); - reftable_table_from_reader(&tabs[i], (*readers)[i]); - } - - err = reftable_new_merged_table(&mt, tabs, n, GIT_SHA1_FORMAT_ID); - EXPECT_ERR(err); - return mt; -} - -static void readers_destroy(struct reftable_reader **readers, size_t n) -{ - int i = 0; - for (; i < n; i++) - reftable_reader_free(readers[i]); - reftable_free(readers); -} - -static void test_merged_between(void) -{ - struct reftable_ref_record r1[] = { { - .refname = (char *) "b", - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 1, 2, 3, 0 }, - } }; - struct reftable_ref_record r2[] = { { - .refname = (char *) "a", - .update_index = 2, - .value_type = REFTABLE_REF_DELETION, - } }; - - struct reftable_ref_record *refs[] = { r1, r2 }; - int sizes[] = { 1, 1 }; - struct strbuf bufs[2] = { STRBUF_INIT, STRBUF_INIT }; - struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; - struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 2); - int i; - struct reftable_ref_record ref = { NULL }; - struct reftable_iterator it = { NULL }; - int err; - - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); - err = reftable_iterator_seek_ref(&it, "a"); - EXPECT_ERR(err); - - err = reftable_iterator_next_ref(&it, &ref); - EXPECT_ERR(err); - EXPECT(ref.update_index == 2); - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - readers_destroy(readers, 2); - reftable_merged_table_free(mt); - for (i = 0; i < ARRAY_SIZE(bufs); i++) { - strbuf_release(&bufs[i]); - } - reftable_free(bs); -} - -static void test_merged(void) -{ - struct reftable_ref_record r1[] = { - { - .refname = (char *) "a", - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 1 }, - }, - { - .refname = (char *) "b", - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 1 }, - }, - { - .refname = (char *) "c", - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 1 }, - } - }; - struct reftable_ref_record r2[] = { { - .refname = (char *) "a", - .update_index = 2, - .value_type = REFTABLE_REF_DELETION, - } }; - struct reftable_ref_record r3[] = { - { - .refname = (char *) "c", - .update_index = 3, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 2 }, - }, - { - .refname = (char *) "d", - .update_index = 3, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 1 }, - }, - }; - - struct reftable_ref_record *want[] = { - &r2[0], - &r1[1], - &r3[0], - &r3[1], - }; - - struct reftable_ref_record *refs[] = { r1, r2, r3 }; - int sizes[3] = { 3, 1, 2 }; - struct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT }; - struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; - struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); - struct reftable_iterator it = { NULL }; - int err; - struct reftable_ref_record *out = NULL; - size_t len = 0; - size_t cap = 0; - int i = 0; - - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); - err = reftable_iterator_seek_ref(&it, "a"); - EXPECT_ERR(err); - EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID); - EXPECT(reftable_merged_table_min_update_index(mt) == 1); - - while (len < 100) { /* cap loops/recursion. */ - struct reftable_ref_record ref = { NULL }; - int err = reftable_iterator_next_ref(&it, &ref); - if (err > 0) - break; - - REFTABLE_ALLOC_GROW(out, len + 1, cap); - out[len++] = ref; - } - reftable_iterator_destroy(&it); - - EXPECT(ARRAY_SIZE(want) == len); - for (i = 0; i < len; i++) { - EXPECT(reftable_ref_record_equal(want[i], &out[i], - GIT_SHA1_RAWSZ)); - } - for (i = 0; i < len; i++) { - reftable_ref_record_release(&out[i]); - } - reftable_free(out); - - for (i = 0; i < 3; i++) { - strbuf_release(&bufs[i]); - } - readers_destroy(readers, 3); - reftable_merged_table_free(mt); - reftable_free(bs); -} - -static struct reftable_merged_table * -merged_table_from_log_records(struct reftable_log_record **logs, - struct reftable_block_source **source, - struct reftable_reader ***readers, int *sizes, - struct strbuf *buf, size_t n) -{ - struct reftable_merged_table *mt = NULL; - struct reftable_table *tabs; - int err; - - REFTABLE_CALLOC_ARRAY(tabs, n); - REFTABLE_CALLOC_ARRAY(*readers, n); - REFTABLE_CALLOC_ARRAY(*source, n); - - for (size_t i = 0; i < n; i++) { - write_test_log_table(&buf[i], logs[i], sizes[i], i + 1); - block_source_from_strbuf(&(*source)[i], &buf[i]); - - err = reftable_new_reader(&(*readers)[i], &(*source)[i], - "name"); - EXPECT_ERR(err); - reftable_table_from_reader(&tabs[i], (*readers)[i]); - } - - err = reftable_new_merged_table(&mt, tabs, n, GIT_SHA1_FORMAT_ID); - EXPECT_ERR(err); - return mt; -} - -static void test_merged_logs(void) -{ - struct reftable_log_record r1[] = { - { - .refname = (char *) "a", - .update_index = 2, - .value_type = REFTABLE_LOG_UPDATE, - .value.update = { - .old_hash = { 2 }, - /* deletion */ - .name = (char *) "jane doe", - .email = (char *) "jane@invalid", - .message = (char *) "message2", - } - }, - { - .refname = (char *) "a", - .update_index = 1, - .value_type = REFTABLE_LOG_UPDATE, - .value.update = { - .old_hash = { 1 }, - .new_hash = { 2 }, - .name = (char *) "jane doe", - .email = (char *) "jane@invalid", - .message = (char *) "message1", - } - }, - }; - struct reftable_log_record r2[] = { - { - .refname = (char *) "a", - .update_index = 3, - .value_type = REFTABLE_LOG_UPDATE, - .value.update = { - .new_hash = { 3 }, - .name = (char *) "jane doe", - .email = (char *) "jane@invalid", - .message = (char *) "message3", - } - }, - }; - struct reftable_log_record r3[] = { - { - .refname = (char *) "a", - .update_index = 2, - .value_type = REFTABLE_LOG_DELETION, - }, - }; - struct reftable_log_record *want[] = { - &r2[0], - &r3[0], - &r1[1], - }; - - struct reftable_log_record *logs[] = { r1, r2, r3 }; - int sizes[3] = { 2, 1, 1 }; - struct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT }; - struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; - struct reftable_merged_table *mt = merged_table_from_log_records( - logs, &bs, &readers, sizes, bufs, 3); - struct reftable_iterator it = { NULL }; - int err; - struct reftable_log_record *out = NULL; - size_t len = 0; - size_t cap = 0; - int i = 0; - - merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); - err = reftable_iterator_seek_log(&it, "a"); - EXPECT_ERR(err); - EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID); - EXPECT(reftable_merged_table_min_update_index(mt) == 1); - - while (len < 100) { /* cap loops/recursion. */ - struct reftable_log_record log = { NULL }; - int err = reftable_iterator_next_log(&it, &log); - if (err > 0) - break; - - REFTABLE_ALLOC_GROW(out, len + 1, cap); - out[len++] = log; - } - reftable_iterator_destroy(&it); - - EXPECT(ARRAY_SIZE(want) == len); - for (i = 0; i < len; i++) { - EXPECT(reftable_log_record_equal(want[i], &out[i], - GIT_SHA1_RAWSZ)); - } - - merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); - err = reftable_iterator_seek_log_at(&it, "a", 2); - EXPECT_ERR(err); - reftable_log_record_release(&out[0]); - err = reftable_iterator_next_log(&it, &out[0]); - EXPECT_ERR(err); - EXPECT(reftable_log_record_equal(&out[0], &r3[0], GIT_SHA1_RAWSZ)); - reftable_iterator_destroy(&it); - - for (i = 0; i < len; i++) { - reftable_log_record_release(&out[i]); - } - reftable_free(out); - - for (i = 0; i < 3; i++) { - strbuf_release(&bufs[i]); - } - readers_destroy(readers, 3); - reftable_merged_table_free(mt); - reftable_free(bs); -} - -static void test_default_write_opts(void) -{ - struct reftable_write_options opts = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - - struct reftable_ref_record rec = { - .refname = (char *) "master", - .update_index = 1, - }; - int err; - struct reftable_block_source source = { NULL }; - struct reftable_table *tab = reftable_calloc(1, sizeof(*tab)); - uint32_t hash_id; - struct reftable_reader *rd = NULL; - struct reftable_merged_table *merged = NULL; - - reftable_writer_set_limits(w, 1, 1); - - err = reftable_writer_add_ref(w, &rec); - EXPECT_ERR(err); - - err = reftable_writer_close(w); - EXPECT_ERR(err); - reftable_writer_free(w); - - block_source_from_strbuf(&source, &buf); - - err = reftable_new_reader(&rd, &source, "filename"); - EXPECT_ERR(err); - - hash_id = reftable_reader_hash_id(rd); - EXPECT(hash_id == GIT_SHA1_FORMAT_ID); - - reftable_table_from_reader(&tab[0], rd); - err = reftable_new_merged_table(&merged, tab, 1, GIT_SHA1_FORMAT_ID); - EXPECT_ERR(err); - - reftable_reader_free(rd); - reftable_merged_table_free(merged); - strbuf_release(&buf); -} - -/* XXX test refs_for(oid) */ - -int merged_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_merged_logs); - RUN_TEST(test_merged_between); - RUN_TEST(test_merged); - RUN_TEST(test_default_write_opts); - return 0; -} diff --git a/reftable/pq.c b/reftable/pq.c index 7fb45d8c60..6ee1164dd3 100644 --- a/reftable/pq.c +++ b/reftable/pq.c @@ -8,6 +8,7 @@ https://developers.google.com/open-source/licenses/bsd #include "pq.h" +#include "reftable-error.h" #include "reftable-record.h" #include "system.h" #include "basics.h" @@ -22,27 +23,21 @@ int pq_less(struct pq_entry *a, struct pq_entry *b) struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq) { - int i = 0; + size_t i = 0; struct pq_entry e = pq->heap[0]; pq->heap[0] = pq->heap[pq->len - 1]; pq->len--; - i = 0; while (i < pq->len) { - int min = i; - int j = 2 * i + 1; - int k = 2 * i + 2; - if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i])) { + size_t min = i; + size_t j = 2 * i + 1; + size_t k = 2 * i + 2; + if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i])) min = j; - } - if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min])) { + if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min])) min = k; - } - - if (min == i) { + if (min == i) break; - } - SWAP(pq->heap[i], pq->heap[min]); i = min; } @@ -50,28 +45,29 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq) return e; } -void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e) +int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e) { - int i = 0; + size_t i = 0; REFTABLE_ALLOC_GROW(pq->heap, pq->len + 1, pq->cap); + if (!pq->heap) + return REFTABLE_OUT_OF_MEMORY_ERROR; pq->heap[pq->len++] = *e; i = pq->len - 1; while (i > 0) { - int j = (i - 1) / 2; - if (pq_less(&pq->heap[j], &pq->heap[i])) { + size_t j = (i - 1) / 2; + if (pq_less(&pq->heap[j], &pq->heap[i])) break; - } - SWAP(pq->heap[j], pq->heap[i]); - i = j; } + + return 0; } void merged_iter_pqueue_release(struct merged_iter_pqueue *pq) { - FREE_AND_NULL(pq->heap); + REFTABLE_FREE_AND_NULL(pq->heap); memset(pq, 0, sizeof(*pq)); } diff --git a/reftable/pq.h b/reftable/pq.h index f796c23179..83c062eeca 100644 --- a/reftable/pq.h +++ b/reftable/pq.h @@ -22,9 +22,8 @@ struct merged_iter_pqueue { size_t cap; }; -void merged_iter_pqueue_check(struct merged_iter_pqueue pq); struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq); -void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e); +int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e); void merged_iter_pqueue_release(struct merged_iter_pqueue *pq); int pq_less(struct pq_entry *a, struct pq_entry *b); diff --git a/reftable/pq_test.c b/reftable/pq_test.c deleted file mode 100644 index b7d3c80cc7..0000000000 --- a/reftable/pq_test.c +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" - -#include "basics.h" -#include "constants.h" -#include "pq.h" -#include "record.h" -#include "reftable-tests.h" -#include "test_framework.h" - -void merged_iter_pqueue_check(struct merged_iter_pqueue pq) -{ - int i; - for (i = 1; i < pq.len; i++) { - int parent = (i - 1) / 2; - - EXPECT(pq_less(&pq.heap[parent], &pq.heap[i])); - } -} - -static void test_pq(void) -{ - struct merged_iter_pqueue pq = { NULL }; - struct reftable_record recs[54]; - int N = ARRAY_SIZE(recs) - 1, i; - char *last = NULL; - - for (i = 0; i < N; i++) { - struct strbuf refname = STRBUF_INIT; - strbuf_addf(&refname, "%02d", i); - - reftable_record_init(&recs[i], BLOCK_TYPE_REF); - recs[i].u.ref.refname = strbuf_detach(&refname, NULL); - } - - i = 1; - do { - struct pq_entry e = { - .rec = &recs[i], - }; - - merged_iter_pqueue_add(&pq, &e); - merged_iter_pqueue_check(pq); - - i = (i * 7) % N; - } while (i != 1); - - while (!merged_iter_pqueue_is_empty(pq)) { - struct pq_entry e = merged_iter_pqueue_remove(&pq); - merged_iter_pqueue_check(pq); - - EXPECT(reftable_record_type(e.rec) == BLOCK_TYPE_REF); - if (last) - EXPECT(strcmp(last, e.rec->u.ref.refname) < 0); - last = e.rec->u.ref.refname; - } - - for (i = 0; i < N; i++) - reftable_record_release(&recs[i]); - merged_iter_pqueue_release(&pq); -} - -int pq_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_pq); - return 0; -} diff --git a/reftable/publicbasics.c b/reftable/publicbasics.c deleted file mode 100644 index 44b84a125e..0000000000 --- a/reftable/publicbasics.c +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" -#include "reftable-malloc.h" - -#include "basics.h" - -static void *(*reftable_malloc_ptr)(size_t sz); -static void *(*reftable_realloc_ptr)(void *, size_t); -static void (*reftable_free_ptr)(void *); - -void *reftable_malloc(size_t sz) -{ - if (reftable_malloc_ptr) - return (*reftable_malloc_ptr)(sz); - return malloc(sz); -} - -void *reftable_realloc(void *p, size_t sz) -{ - if (reftable_realloc_ptr) - return (*reftable_realloc_ptr)(p, sz); - return realloc(p, sz); -} - -void reftable_free(void *p) -{ - if (reftable_free_ptr) - reftable_free_ptr(p); - else - free(p); -} - -void *reftable_calloc(size_t nelem, size_t elsize) -{ - size_t sz = st_mult(nelem, elsize); - void *p = reftable_malloc(sz); - memset(p, 0, sz); - return p; -} - -void reftable_set_alloc(void *(*malloc)(size_t), - void *(*realloc)(void *, size_t), void (*free)(void *)) -{ - reftable_malloc_ptr = malloc; - reftable_realloc_ptr = realloc; - reftable_free_ptr = free; -} - -int hash_size(uint32_t id) -{ - switch (id) { - case 0: - case GIT_SHA1_FORMAT_ID: - return GIT_SHA1_RAWSZ; - case GIT_SHA256_FORMAT_ID: - return GIT_SHA256_RAWSZ; - } - abort(); -} diff --git a/reftable/reader.c b/reftable/reader.c index 29c99e2269..ea82955c9b 100644 --- a/reftable/reader.c +++ b/reftable/reader.c @@ -11,11 +11,9 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" #include "block.h" #include "constants.h" -#include "generic.h" #include "iter.h" #include "record.h" #include "reftable-error.h" -#include "reftable-generic.h" uint64_t block_source_size(struct reftable_block_source *source) { @@ -69,7 +67,7 @@ static int reader_get_block(struct reftable_reader *r, return block_source_read_block(&r->source, dest, off, sz); } -uint32_t reftable_reader_hash_id(struct reftable_reader *r) +enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r) { return r->hash_id; } @@ -109,18 +107,20 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, f += 8; if (r->version == 1) { - r->hash_id = GIT_SHA1_FORMAT_ID; + r->hash_id = REFTABLE_HASH_SHA1; } else { - r->hash_id = get_be32(f); - switch (r->hash_id) { - case GIT_SHA1_FORMAT_ID: + switch (get_be32(f)) { + case REFTABLE_FORMAT_ID_SHA1: + r->hash_id = REFTABLE_HASH_SHA1; break; - case GIT_SHA256_FORMAT_ID: + case REFTABLE_FORMAT_ID_SHA256: + r->hash_id = REFTABLE_HASH_SHA256; break; default: err = REFTABLE_FORMAT_ERROR; goto done; } + f += 4; } @@ -164,58 +164,6 @@ done: return err; } -int init_reader(struct reftable_reader *r, struct reftable_block_source *source, - const char *name) -{ - struct reftable_block footer = { NULL }; - struct reftable_block header = { NULL }; - int err = 0; - uint64_t file_size = block_source_size(source); - - /* Need +1 to read type of first block. */ - uint32_t read_size = header_size(2) + 1; /* read v2 because it's larger. */ - memset(r, 0, sizeof(struct reftable_reader)); - - if (read_size > file_size) { - err = REFTABLE_FORMAT_ERROR; - goto done; - } - - err = block_source_read_block(source, &header, 0, read_size); - if (err != read_size) { - err = REFTABLE_IO_ERROR; - goto done; - } - - if (memcmp(header.data, "REFT", 4)) { - err = REFTABLE_FORMAT_ERROR; - goto done; - } - r->version = header.data[4]; - if (r->version != 1 && r->version != 2) { - err = REFTABLE_FORMAT_ERROR; - goto done; - } - - r->size = file_size - footer_size(r->version); - r->source = *source; - r->name = xstrdup(name); - r->hash_id = 0; - - err = block_source_read_block(source, &footer, r->size, - footer_size(r->version)); - if (err != footer_size(r->version)) { - err = REFTABLE_IO_ERROR; - goto done; - } - - err = parse_footer(r, footer.data, header.data); -done: - reftable_block_done(&footer); - reftable_block_done(&header); - return err; -} - struct table_iter { struct reftable_reader *r; uint8_t typ; @@ -229,6 +177,7 @@ static int table_iter_init(struct table_iter *ti, struct reftable_reader *r) { struct block_iter bi = BLOCK_ITER_INIT; memset(ti, 0, sizeof(*ti)); + reftable_reader_incref(r); ti->r = r; ti->bi = bi; return 0; @@ -316,6 +265,7 @@ static void table_iter_close(struct table_iter *ti) { table_iter_block_done(ti); block_iter_close(&ti->bi); + reftable_reader_decref(ti->r); } static int table_iter_next_block(struct table_iter *ti) @@ -380,6 +330,7 @@ static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ) ti->typ = block_reader_type(&ti->br); ti->block_off = off; block_iter_seek_start(&ti->bi, &ti->br); + ti->is_finished = 0; return 0; } @@ -401,13 +352,15 @@ static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index) static int table_iter_seek_linear(struct table_iter *ti, struct reftable_record *want) { - struct strbuf want_key = STRBUF_INIT; - struct strbuf got_key = STRBUF_INIT; + struct reftable_buf want_key = REFTABLE_BUF_INIT; + struct reftable_buf got_key = REFTABLE_BUF_INIT; struct reftable_record rec; int err; reftable_record_init(&rec, reftable_record_type(want)); - reftable_record_key(want, &want_key); + err = reftable_record_key(want, &want_key); + if (err < 0) + goto done; /* * First we need to locate the block that must contain our record. To @@ -452,7 +405,7 @@ static int table_iter_seek_linear(struct table_iter *ti, if (err < 0) goto done; - if (strbuf_cmp(&got_key, &want_key) > 0) { + if (reftable_buf_cmp(&got_key, &want_key) > 0) { table_iter_block_done(&next); break; } @@ -473,8 +426,8 @@ static int table_iter_seek_linear(struct table_iter *ti, done: reftable_record_release(&rec); - strbuf_release(&want_key); - strbuf_release(&got_key); + reftable_buf_release(&want_key); + reftable_buf_release(&got_key); return err; } @@ -482,15 +435,17 @@ static int table_iter_seek_indexed(struct table_iter *ti, struct reftable_record *rec) { struct reftable_record want_index = { - .type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT } + .type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT } }; struct reftable_record index_result = { .type = BLOCK_TYPE_INDEX, - .u.idx = { .last_key = STRBUF_INIT }, + .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int err; - reftable_record_key(rec, &want_index.u.idx.last_key); + err = reftable_record_key(rec, &want_index.u.idx.last_key); + if (err < 0) + goto done; /* * The index may consist of multiple levels, where each level may have @@ -605,59 +560,131 @@ static void iterator_from_table_iter(struct reftable_iterator *it, it->ops = &table_iter_vtable; } -static void reader_init_iter(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t typ) +int reader_init_iter(struct reftable_reader *r, + struct reftable_iterator *it, + uint8_t typ) { struct reftable_reader_offsets *offs = reader_offsets_for(r, typ); if (offs->is_present) { struct table_iter *ti; REFTABLE_ALLOC_ARRAY(ti, 1); + if (!ti) + return REFTABLE_OUT_OF_MEMORY_ERROR; + table_iter_init(ti, r); iterator_from_table_iter(it, ti); } else { iterator_set_empty(it); } -} -void reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it) -{ - reader_init_iter(r, it, BLOCK_TYPE_REF); + return 0; } -void reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it) +int reftable_reader_init_ref_iterator(struct reftable_reader *r, + struct reftable_iterator *it) { - reader_init_iter(r, it, BLOCK_TYPE_LOG); + return reader_init_iter(r, it, BLOCK_TYPE_REF); } -void reader_close(struct reftable_reader *r) +int reftable_reader_init_log_iterator(struct reftable_reader *r, + struct reftable_iterator *it) { - block_source_close(&r->source); - FREE_AND_NULL(r->name); + return reader_init_iter(r, it, BLOCK_TYPE_LOG); } -int reftable_new_reader(struct reftable_reader **p, - struct reftable_block_source *src, char const *name) +int reftable_reader_new(struct reftable_reader **out, + struct reftable_block_source *source, char const *name) { - struct reftable_reader *rd = reftable_calloc(1, sizeof(*rd)); - int err = init_reader(rd, src, name); - if (err == 0) { - *p = rd; - } else { - block_source_close(src); - reftable_free(rd); + struct reftable_block footer = { 0 }; + struct reftable_block header = { 0 }; + struct reftable_reader *r; + uint64_t file_size = block_source_size(source); + uint32_t read_size; + int err; + + REFTABLE_CALLOC_ARRAY(r, 1); + if (!r) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + + /* + * We need one extra byte to read the type of first block. We also + * pretend to always be reading v2 of the format because it is larger. + */ + read_size = header_size(2) + 1; + if (read_size > file_size) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } + + err = block_source_read_block(source, &header, 0, read_size); + if (err != read_size) { + err = REFTABLE_IO_ERROR; + goto done; + } + + if (memcmp(header.data, "REFT", 4)) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } + r->version = header.data[4]; + if (r->version != 1 && r->version != 2) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } + + r->size = file_size - footer_size(r->version); + r->source = *source; + r->name = reftable_strdup(name); + if (!r->name) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + r->hash_id = 0; + r->refcount = 1; + + err = block_source_read_block(source, &footer, r->size, + footer_size(r->version)); + if (err != footer_size(r->version)) { + err = REFTABLE_IO_ERROR; + goto done; + } + + err = parse_footer(r, footer.data, header.data); + if (err) + goto done; + + *out = r; + +done: + reftable_block_done(&footer); + reftable_block_done(&header); + if (err) { + reftable_free(r); + block_source_close(source); } return err; } -void reftable_reader_free(struct reftable_reader *r) +void reftable_reader_incref(struct reftable_reader *r) +{ + if (!r->refcount) + BUG("cannot increment ref counter of dead reader"); + r->refcount++; +} + +void reftable_reader_decref(struct reftable_reader *r) { if (!r) return; - reader_close(r); + if (!r->refcount) + BUG("cannot decrement ref counter of dead reader"); + if (--r->refcount) + return; + block_source_close(&r->source); + REFTABLE_FREE_AND_NULL(r->name); reftable_free(r); } @@ -681,7 +708,10 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r, struct indexed_table_ref_iter *itr = NULL; /* Look through the reverse index. */ - reader_init_iter(r, &oit, BLOCK_TYPE_OBJ); + err = reader_init_iter(r, &oit, BLOCK_TYPE_OBJ); + if (err < 0) + goto done; + err = iterator_seek(&oit, &want); if (err != 0) goto done; @@ -699,7 +729,7 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r, goto done; } - err = new_indexed_table_ref_iter(&itr, r, oid, hash_size(r->hash_id), + err = indexed_table_ref_iter_new(&itr, r, oid, hash_size(r->hash_id), got.u.obj.offsets, got.u.obj.offset_len); if (err < 0) @@ -724,23 +754,40 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, int err; REFTABLE_ALLOC_ARRAY(ti, 1); + if (!ti) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + table_iter_init(ti, r); err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0); - if (err < 0) { - reftable_free(ti); - return err; - } + if (err < 0) + goto out; - filter = reftable_malloc(sizeof(struct filtering_ref_iterator)); + filter = reftable_malloc(sizeof(*filter)); + if (!filter) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } *filter = empty; - strbuf_add(&filter->oid, oid, oid_len); - reftable_table_from_reader(&filter->tab, r); - filter->double_check = 0; + err = reftable_buf_add(&filter->oid, oid, oid_len); + if (err < 0) + goto out; + iterator_from_table_iter(&filter->it, ti); iterator_from_filtering_ref_iterator(it, filter); - return 0; + + err = 0; + +out: + if (err < 0) { + if (ti) + table_iter_close(ti); + reftable_free(ti); + } + return err; } int reftable_reader_refs_for(struct reftable_reader *r, @@ -761,66 +808,6 @@ uint64_t reftable_reader_min_update_index(struct reftable_reader *r) return r->min_update_index; } -/* generic table interface. */ - -static void reftable_reader_init_iter_void(void *tab, - struct reftable_iterator *it, - uint8_t typ) -{ - reader_init_iter(tab, it, typ); -} - -static uint32_t reftable_reader_hash_id_void(void *tab) -{ - return reftable_reader_hash_id(tab); -} - -static uint64_t reftable_reader_min_update_index_void(void *tab) -{ - return reftable_reader_min_update_index(tab); -} - -static uint64_t reftable_reader_max_update_index_void(void *tab) -{ - return reftable_reader_max_update_index(tab); -} - -static struct reftable_table_vtable reader_vtable = { - .init_iter = reftable_reader_init_iter_void, - .hash_id = reftable_reader_hash_id_void, - .min_update_index = reftable_reader_min_update_index_void, - .max_update_index = reftable_reader_max_update_index_void, -}; - -void reftable_table_from_reader(struct reftable_table *tab, - struct reftable_reader *reader) -{ - assert(!tab->ops); - tab->ops = &reader_vtable; - tab->table_arg = reader; -} - - -int reftable_reader_print_file(const char *tablename) -{ - struct reftable_block_source src = { NULL }; - int err = reftable_block_source_from_file(&src, tablename); - struct reftable_reader *r = NULL; - struct reftable_table tab = { NULL }; - if (err < 0) - goto done; - - err = reftable_new_reader(&r, &src, tablename); - if (err < 0) - goto done; - - reftable_table_from_reader(&tab, r); - err = reftable_table_print(&tab); -done: - reftable_reader_free(r); - return err; -} - int reftable_reader_print_blocks(const char *tablename) { struct { @@ -850,7 +837,7 @@ int reftable_reader_print_blocks(const char *tablename) if (err < 0) goto done; - err = reftable_new_reader(&r, &src, tablename); + err = reftable_reader_new(&r, &src, tablename); if (err < 0) goto done; @@ -881,7 +868,7 @@ int reftable_reader_print_blocks(const char *tablename) } done: - reftable_reader_free(r); + reftable_reader_decref(r); table_iter_close(&ti); return err; } diff --git a/reftable/reader.h b/reftable/reader.h index e869165f23..d2b48a4849 100644 --- a/reftable/reader.h +++ b/reftable/reader.h @@ -30,15 +30,15 @@ struct reftable_reader_offsets { /* The state for reading a reftable file. */ struct reftable_reader { - /* for convience, associate a name with the instance. */ + /* for convenience, associate a name with the instance. */ char *name; struct reftable_block_source source; /* Size of the file, excluding the footer. */ uint64_t size; - /* 'sha1' for SHA1, 's256' for SHA-256 */ - uint32_t hash_id; + /* The hash function used for ref records. */ + enum reftable_hash hash_id; uint32_t block_size; uint64_t min_update_index; @@ -50,13 +50,16 @@ struct reftable_reader { struct reftable_reader_offsets ref_offsets; struct reftable_reader_offsets obj_offsets; struct reftable_reader_offsets log_offsets; + + uint64_t refcount; }; -int init_reader(struct reftable_reader *r, struct reftable_block_source *source, - const char *name); -void reader_close(struct reftable_reader *r); const char *reader_name(struct reftable_reader *r); +int reader_init_iter(struct reftable_reader *r, + struct reftable_iterator *it, + uint8_t typ); + /* initialize a block reader to read from `r` */ int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br, uint64_t next_off, uint8_t want_typ); diff --git a/reftable/readwrite_test.c b/reftable/readwrite_test.c deleted file mode 100644 index f411abfe9c..0000000000 --- a/reftable/readwrite_test.c +++ /dev/null @@ -1,979 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" - -#include "basics.h" -#include "block.h" -#include "blocksource.h" -#include "reader.h" -#include "record.h" -#include "test_framework.h" -#include "reftable-tests.h" -#include "reftable-writer.h" - -static const int update_index = 5; - -static void test_buffer(void) -{ - struct strbuf buf = STRBUF_INIT; - struct reftable_block_source source = { NULL }; - struct reftable_block out = { NULL }; - int n; - uint8_t in[] = "hello"; - strbuf_add(&buf, in, sizeof(in)); - block_source_from_strbuf(&source, &buf); - EXPECT(block_source_size(&source) == 6); - n = block_source_read_block(&source, &out, 0, sizeof(in)); - EXPECT(n == sizeof(in)); - EXPECT(!memcmp(in, out.data, n)); - reftable_block_done(&out); - - n = block_source_read_block(&source, &out, 1, 2); - EXPECT(n == 2); - EXPECT(!memcmp(out.data, "el", 2)); - - reftable_block_done(&out); - block_source_close(&source); - strbuf_release(&buf); -} - -static void write_table(char ***names, struct strbuf *buf, int N, - int block_size, uint32_t hash_id) -{ - struct reftable_write_options opts = { - .block_size = block_size, - .hash_id = hash_id, - }; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts); - struct reftable_ref_record ref = { NULL }; - int i = 0, n; - struct reftable_log_record log = { NULL }; - const struct reftable_stats *stats = NULL; - - REFTABLE_CALLOC_ARRAY(*names, N + 1); - - reftable_writer_set_limits(w, update_index, update_index); - for (i = 0; i < N; i++) { - char name[100]; - int n; - - snprintf(name, sizeof(name), "refs/heads/branch%02d", i); - - ref.refname = name; - ref.update_index = update_index; - ref.value_type = REFTABLE_REF_VAL1; - set_test_hash(ref.value.val1, i); - (*names)[i] = xstrdup(name); - - n = reftable_writer_add_ref(w, &ref); - EXPECT(n == 0); - } - - for (i = 0; i < N; i++) { - char name[100]; - int n; - - snprintf(name, sizeof(name), "refs/heads/branch%02d", i); - - log.refname = name; - log.update_index = update_index; - log.value_type = REFTABLE_LOG_UPDATE; - set_test_hash(log.value.update.new_hash, i); - log.value.update.message = (char *) "message"; - - n = reftable_writer_add_log(w, &log); - EXPECT(n == 0); - } - - n = reftable_writer_close(w); - EXPECT(n == 0); - - stats = reftable_writer_stats(w); - for (i = 0; i < stats->ref_stats.blocks; i++) { - int off = i * opts.block_size; - if (off == 0) { - off = header_size( - (hash_id == GIT_SHA256_FORMAT_ID) ? 2 : 1); - } - EXPECT(buf->buf[off] == 'r'); - } - - EXPECT(stats->log_stats.blocks > 0); - reftable_writer_free(w); -} - -static void test_log_buffer_size(void) -{ - struct strbuf buf = STRBUF_INIT; - struct reftable_write_options opts = { - .block_size = 4096, - }; - int err; - int i; - struct reftable_log_record - log = { .refname = (char *) "refs/heads/master", - .update_index = 0xa, - .value_type = REFTABLE_LOG_UPDATE, - .value = { .update = { - .name = (char *) "Han-Wen Nienhuys", - .email = (char *) "hanwen@google.com", - .tz_offset = 100, - .time = 0x5e430672, - .message = (char *) "commit: 9\n", - } } }; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - - /* This tests buffer extension for log compression. Must use a random - hash, to ensure that the compressed part is larger than the original. - */ - for (i = 0; i < GIT_SHA1_RAWSZ; i++) { - log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); - log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); - } - reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - EXPECT_ERR(err); - err = reftable_writer_close(w); - EXPECT_ERR(err); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_log_overflow(void) -{ - struct strbuf buf = STRBUF_INIT; - char msg[256] = { 0 }; - struct reftable_write_options opts = { - .block_size = ARRAY_SIZE(msg), - }; - int err; - struct reftable_log_record log = { - .refname = (char *) "refs/heads/master", - .update_index = 0xa, - .value_type = REFTABLE_LOG_UPDATE, - .value = { - .update = { - .old_hash = { 1 }, - .new_hash = { 2 }, - .name = (char *) "Han-Wen Nienhuys", - .email = (char *) "hanwen@google.com", - .tz_offset = 100, - .time = 0x5e430672, - .message = msg, - }, - }, - }; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - - memset(msg, 'x', sizeof(msg) - 1); - reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - EXPECT(err == REFTABLE_ENTRY_TOO_BIG_ERROR); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_log_write_read(void) -{ - int N = 2; - char **names = reftable_calloc(N + 1, sizeof(*names)); - int err; - struct reftable_write_options opts = { - .block_size = 256, - }; - struct reftable_ref_record ref = { NULL }; - int i = 0; - struct reftable_log_record log = { NULL }; - int n; - struct reftable_iterator it = { NULL }; - struct reftable_reader rd = { NULL }; - struct reftable_block_source source = { NULL }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - const struct reftable_stats *stats = NULL; - reftable_writer_set_limits(w, 0, N); - for (i = 0; i < N; i++) { - char name[256]; - struct reftable_ref_record ref = { NULL }; - snprintf(name, sizeof(name), "b%02d%0*d", i, 130, 7); - names[i] = xstrdup(name); - ref.refname = name; - ref.update_index = i; - - err = reftable_writer_add_ref(w, &ref); - EXPECT_ERR(err); - } - for (i = 0; i < N; i++) { - struct reftable_log_record log = { NULL }; - - log.refname = names[i]; - log.update_index = i; - log.value_type = REFTABLE_LOG_UPDATE; - set_test_hash(log.value.update.old_hash, i); - set_test_hash(log.value.update.new_hash, i + 1); - - err = reftable_writer_add_log(w, &log); - EXPECT_ERR(err); - } - - n = reftable_writer_close(w); - EXPECT(n == 0); - - stats = reftable_writer_stats(w); - EXPECT(stats->log_stats.blocks > 0); - reftable_writer_free(w); - w = NULL; - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.log"); - EXPECT_ERR(err); - - reftable_reader_init_ref_iterator(&rd, &it); - - err = reftable_iterator_seek_ref(&it, names[N - 1]); - EXPECT_ERR(err); - - err = reftable_iterator_next_ref(&it, &ref); - EXPECT_ERR(err); - - /* end of iteration. */ - err = reftable_iterator_next_ref(&it, &ref); - EXPECT(0 < err); - - reftable_iterator_destroy(&it); - reftable_ref_record_release(&ref); - - reftable_reader_init_log_iterator(&rd, &it); - - err = reftable_iterator_seek_log(&it, ""); - EXPECT_ERR(err); - - i = 0; - while (1) { - int err = reftable_iterator_next_log(&it, &log); - if (err > 0) { - break; - } - - EXPECT_ERR(err); - EXPECT_STREQ(names[i], log.refname); - EXPECT(i == log.update_index); - i++; - reftable_log_record_release(&log); - } - - EXPECT(i == N); - reftable_iterator_destroy(&it); - - /* cleanup. */ - strbuf_release(&buf); - free_names(names); - reader_close(&rd); -} - -static void test_log_zlib_corruption(void) -{ - struct reftable_write_options opts = { - .block_size = 256, - }; - struct reftable_iterator it = { 0 }; - struct reftable_reader rd = { 0 }; - struct reftable_block_source source = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - const struct reftable_stats *stats = NULL; - char message[100] = { 0 }; - int err, i, n; - struct reftable_log_record log = { - .refname = (char *) "refname", - .value_type = REFTABLE_LOG_UPDATE, - .value = { - .update = { - .new_hash = { 1 }, - .old_hash = { 2 }, - .name = (char *) "My Name", - .email = (char *) "myname@invalid", - .message = message, - }, - }, - }; - - for (i = 0; i < sizeof(message) - 1; i++) - message[i] = (uint8_t)(git_rand() % 64 + ' '); - - reftable_writer_set_limits(w, 1, 1); - - err = reftable_writer_add_log(w, &log); - EXPECT_ERR(err); - - n = reftable_writer_close(w); - EXPECT(n == 0); - - stats = reftable_writer_stats(w); - EXPECT(stats->log_stats.blocks > 0); - reftable_writer_free(w); - w = NULL; - - /* corrupt the data. */ - buf.buf[50] ^= 0x99; - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.log"); - EXPECT_ERR(err); - - reftable_reader_init_log_iterator(&rd, &it); - err = reftable_iterator_seek_log(&it, "refname"); - EXPECT(err == REFTABLE_ZLIB_ERROR); - - reftable_iterator_destroy(&it); - - /* cleanup. */ - strbuf_release(&buf); - reader_close(&rd); -} - -static void test_table_read_write_sequential(void) -{ - char **names; - struct strbuf buf = STRBUF_INIT; - int N = 50; - struct reftable_iterator it = { NULL }; - struct reftable_block_source source = { NULL }; - struct reftable_reader rd = { NULL }; - int err = 0; - int j = 0; - - write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID); - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.ref"); - EXPECT_ERR(err); - - reftable_reader_init_ref_iterator(&rd, &it); - err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); - - while (1) { - struct reftable_ref_record ref = { NULL }; - int r = reftable_iterator_next_ref(&it, &ref); - EXPECT(r >= 0); - if (r > 0) { - break; - } - EXPECT(0 == strcmp(names[j], ref.refname)); - EXPECT(update_index == ref.update_index); - - j++; - reftable_ref_record_release(&ref); - } - EXPECT(j == N); - reftable_iterator_destroy(&it); - strbuf_release(&buf); - free_names(names); - - reader_close(&rd); -} - -static void test_table_write_small_table(void) -{ - char **names; - struct strbuf buf = STRBUF_INIT; - int N = 1; - write_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID); - EXPECT(buf.len < 200); - strbuf_release(&buf); - free_names(names); -} - -static void test_table_read_api(void) -{ - char **names; - struct strbuf buf = STRBUF_INIT; - int N = 50; - struct reftable_reader rd = { NULL }; - struct reftable_block_source source = { NULL }; - int err; - int i; - struct reftable_log_record log = { NULL }; - struct reftable_iterator it = { NULL }; - - write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID); - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.ref"); - EXPECT_ERR(err); - - reftable_reader_init_ref_iterator(&rd, &it); - err = reftable_iterator_seek_ref(&it, names[0]); - EXPECT_ERR(err); - - err = reftable_iterator_next_log(&it, &log); - EXPECT(err == REFTABLE_API_ERROR); - - strbuf_release(&buf); - for (i = 0; i < N; i++) { - reftable_free(names[i]); - } - reftable_iterator_destroy(&it); - reftable_free(names); - reader_close(&rd); - strbuf_release(&buf); -} - -static void test_table_read_write_seek(int index, int hash_id) -{ - char **names; - struct strbuf buf = STRBUF_INIT; - int N = 50; - struct reftable_reader rd = { NULL }; - struct reftable_block_source source = { NULL }; - int err; - int i = 0; - - struct reftable_iterator it = { NULL }; - struct strbuf pastLast = STRBUF_INIT; - struct reftable_ref_record ref = { NULL }; - - write_table(&names, &buf, N, 256, hash_id); - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.ref"); - EXPECT_ERR(err); - EXPECT(hash_id == reftable_reader_hash_id(&rd)); - - if (!index) { - rd.ref_offsets.index_offset = 0; - } else { - EXPECT(rd.ref_offsets.index_offset > 0); - } - - for (i = 1; i < N; i++) { - reftable_reader_init_ref_iterator(&rd, &it); - err = reftable_iterator_seek_ref(&it, names[i]); - EXPECT_ERR(err); - err = reftable_iterator_next_ref(&it, &ref); - EXPECT_ERR(err); - EXPECT(0 == strcmp(names[i], ref.refname)); - EXPECT(REFTABLE_REF_VAL1 == ref.value_type); - EXPECT(i == ref.value.val1[0]); - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - } - - strbuf_addstr(&pastLast, names[N - 1]); - strbuf_addstr(&pastLast, "/"); - - reftable_reader_init_ref_iterator(&rd, &it); - err = reftable_iterator_seek_ref(&it, pastLast.buf); - if (err == 0) { - struct reftable_ref_record ref = { NULL }; - int err = reftable_iterator_next_ref(&it, &ref); - EXPECT(err > 0); - } else { - EXPECT(err > 0); - } - - strbuf_release(&pastLast); - reftable_iterator_destroy(&it); - - strbuf_release(&buf); - for (i = 0; i < N; i++) { - reftable_free(names[i]); - } - reftable_free(names); - reader_close(&rd); -} - -static void test_table_read_write_seek_linear(void) -{ - test_table_read_write_seek(0, GIT_SHA1_FORMAT_ID); -} - -static void test_table_read_write_seek_linear_sha256(void) -{ - test_table_read_write_seek(0, GIT_SHA256_FORMAT_ID); -} - -static void test_table_read_write_seek_index(void) -{ - test_table_read_write_seek(1, GIT_SHA1_FORMAT_ID); -} - -static void test_table_refs_for(int indexed) -{ - int N = 50; - char **want_names = reftable_calloc(N + 1, sizeof(*want_names)); - int want_names_len = 0; - uint8_t want_hash[GIT_SHA1_RAWSZ]; - - struct reftable_write_options opts = { - .block_size = 256, - }; - struct reftable_ref_record ref = { NULL }; - int i = 0; - int n; - int err; - struct reftable_reader rd; - struct reftable_block_source source = { NULL }; - - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - - struct reftable_iterator it = { NULL }; - int j; - - set_test_hash(want_hash, 4); - - for (i = 0; i < N; i++) { - uint8_t hash[GIT_SHA1_RAWSZ]; - char fill[51] = { 0 }; - char name[100]; - struct reftable_ref_record ref = { NULL }; - - memset(hash, i, sizeof(hash)); - memset(fill, 'x', 50); - /* Put the variable part in the start */ - snprintf(name, sizeof(name), "br%02d%s", i, fill); - name[40] = 0; - ref.refname = name; - - ref.value_type = REFTABLE_REF_VAL2; - set_test_hash(ref.value.val2.value, i / 4); - set_test_hash(ref.value.val2.target_value, 3 + i / 4); - - /* 80 bytes / entry, so 3 entries per block. Yields 17 - */ - /* blocks. */ - n = reftable_writer_add_ref(w, &ref); - EXPECT(n == 0); - - if (!memcmp(ref.value.val2.value, want_hash, GIT_SHA1_RAWSZ) || - !memcmp(ref.value.val2.target_value, want_hash, GIT_SHA1_RAWSZ)) { - want_names[want_names_len++] = xstrdup(name); - } - } - - n = reftable_writer_close(w); - EXPECT(n == 0); - - reftable_writer_free(w); - w = NULL; - - block_source_from_strbuf(&source, &buf); - - err = init_reader(&rd, &source, "file.ref"); - EXPECT_ERR(err); - if (!indexed) { - rd.obj_offsets.is_present = 0; - } - - reftable_reader_init_ref_iterator(&rd, &it); - err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); - reftable_iterator_destroy(&it); - - err = reftable_reader_refs_for(&rd, &it, want_hash); - EXPECT_ERR(err); - - j = 0; - while (1) { - int err = reftable_iterator_next_ref(&it, &ref); - EXPECT(err >= 0); - if (err > 0) { - break; - } - - EXPECT(j < want_names_len); - EXPECT(0 == strcmp(ref.refname, want_names[j])); - j++; - reftable_ref_record_release(&ref); - } - EXPECT(j == want_names_len); - - strbuf_release(&buf); - free_names(want_names); - reftable_iterator_destroy(&it); - reader_close(&rd); -} - -static void test_table_refs_for_no_index(void) -{ - test_table_refs_for(0); -} - -static void test_table_refs_for_obj_index(void) -{ - test_table_refs_for(1); -} - -static void test_write_empty_table(void) -{ - struct reftable_write_options opts = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - struct reftable_block_source source = { NULL }; - struct reftable_reader *rd = NULL; - struct reftable_ref_record rec = { NULL }; - struct reftable_iterator it = { NULL }; - int err; - - reftable_writer_set_limits(w, 1, 1); - - err = reftable_writer_close(w); - EXPECT(err == REFTABLE_EMPTY_TABLE_ERROR); - reftable_writer_free(w); - - EXPECT(buf.len == header_size(1) + footer_size(1)); - - block_source_from_strbuf(&source, &buf); - - err = reftable_new_reader(&rd, &source, "filename"); - EXPECT_ERR(err); - - reftable_reader_init_ref_iterator(rd, &it); - err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); - - err = reftable_iterator_next_ref(&it, &rec); - EXPECT(err > 0); - - reftable_iterator_destroy(&it); - reftable_reader_free(rd); - strbuf_release(&buf); -} - -static void test_write_object_id_min_length(void) -{ - struct reftable_write_options opts = { - .block_size = 75, - }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - struct reftable_ref_record ref = { - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = {42}, - }; - int err; - int i; - - reftable_writer_set_limits(w, 1, 1); - - /* Write the same hash in many refs. If there is only 1 hash, the - * disambiguating prefix is length 0 */ - for (i = 0; i < 256; i++) { - char name[256]; - snprintf(name, sizeof(name), "ref%05d", i); - ref.refname = name; - err = reftable_writer_add_ref(w, &ref); - EXPECT_ERR(err); - } - - err = reftable_writer_close(w); - EXPECT_ERR(err); - EXPECT(reftable_writer_stats(w)->object_id_len == 2); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_write_object_id_length(void) -{ - struct reftable_write_options opts = { - .block_size = 75, - }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - struct reftable_ref_record ref = { - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = {42}, - }; - int err; - int i; - - reftable_writer_set_limits(w, 1, 1); - - /* Write the same hash in many refs. If there is only 1 hash, the - * disambiguating prefix is length 0 */ - for (i = 0; i < 256; i++) { - char name[256]; - snprintf(name, sizeof(name), "ref%05d", i); - ref.refname = name; - ref.value.val1[15] = i; - err = reftable_writer_add_ref(w, &ref); - EXPECT_ERR(err); - } - - err = reftable_writer_close(w); - EXPECT_ERR(err); - EXPECT(reftable_writer_stats(w)->object_id_len == 16); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_write_empty_key(void) -{ - struct reftable_write_options opts = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - struct reftable_ref_record ref = { - .refname = (char *) "", - .update_index = 1, - .value_type = REFTABLE_REF_DELETION, - }; - int err; - - reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &ref); - EXPECT(err == REFTABLE_API_ERROR); - - err = reftable_writer_close(w); - EXPECT(err == REFTABLE_EMPTY_TABLE_ERROR); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_write_key_order(void) -{ - struct reftable_write_options opts = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_writer *w = - reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - struct reftable_ref_record refs[2] = { - { - .refname = (char *) "b", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value = { - .symref = (char *) "target", - }, - }, { - .refname = (char *) "a", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value = { - .symref = (char *) "target", - }, - } - }; - int err; - - reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &refs[0]); - EXPECT_ERR(err); - err = reftable_writer_add_ref(w, &refs[1]); - EXPECT(err == REFTABLE_API_ERROR); - reftable_writer_close(w); - reftable_writer_free(w); - strbuf_release(&buf); -} - -static void test_write_multiple_indices(void) -{ - struct reftable_write_options opts = { - .block_size = 100, - }; - struct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT; - struct reftable_block_source source = { 0 }; - struct reftable_iterator it = { 0 }; - const struct reftable_stats *stats; - struct reftable_writer *writer; - struct reftable_reader *reader; - int err, i; - - writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts); - reftable_writer_set_limits(writer, 1, 1); - for (i = 0; i < 100; i++) { - struct reftable_ref_record ref = { - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = {i}, - }; - - strbuf_reset(&buf); - strbuf_addf(&buf, "refs/heads/%04d", i); - ref.refname = buf.buf, - - err = reftable_writer_add_ref(writer, &ref); - EXPECT_ERR(err); - } - - for (i = 0; i < 100; i++) { - struct reftable_log_record log = { - .update_index = 1, - .value_type = REFTABLE_LOG_UPDATE, - .value.update = { - .old_hash = { i }, - .new_hash = { i }, - }, - }; - - strbuf_reset(&buf); - strbuf_addf(&buf, "refs/heads/%04d", i); - log.refname = buf.buf, - - err = reftable_writer_add_log(writer, &log); - EXPECT_ERR(err); - } - - reftable_writer_close(writer); - - /* - * The written data should be sufficiently large to result in indices - * for each of the block types. - */ - stats = reftable_writer_stats(writer); - EXPECT(stats->ref_stats.index_offset > 0); - EXPECT(stats->obj_stats.index_offset > 0); - EXPECT(stats->log_stats.index_offset > 0); - - block_source_from_strbuf(&source, &writer_buf); - err = reftable_new_reader(&reader, &source, "filename"); - EXPECT_ERR(err); - - /* - * Seeking the log uses the log index now. In case there is any - * confusion regarding indices we would notice here. - */ - reftable_reader_init_log_iterator(reader, &it); - err = reftable_iterator_seek_log(&it, ""); - EXPECT_ERR(err); - - reftable_iterator_destroy(&it); - reftable_writer_free(writer); - reftable_reader_free(reader); - strbuf_release(&writer_buf); - strbuf_release(&buf); -} - -static void test_write_multi_level_index(void) -{ - struct reftable_write_options opts = { - .block_size = 100, - }; - struct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT; - struct reftable_block_source source = { 0 }; - struct reftable_iterator it = { 0 }; - const struct reftable_stats *stats; - struct reftable_writer *writer; - struct reftable_reader *reader; - int err; - - writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts); - reftable_writer_set_limits(writer, 1, 1); - for (size_t i = 0; i < 200; i++) { - struct reftable_ref_record ref = { - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = {i}, - }; - - strbuf_reset(&buf); - strbuf_addf(&buf, "refs/heads/%03" PRIuMAX, (uintmax_t)i); - ref.refname = buf.buf, - - err = reftable_writer_add_ref(writer, &ref); - EXPECT_ERR(err); - } - reftable_writer_close(writer); - - /* - * The written refs should be sufficiently large to result in a - * multi-level index. - */ - stats = reftable_writer_stats(writer); - EXPECT(stats->ref_stats.max_index_level == 2); - - block_source_from_strbuf(&source, &writer_buf); - err = reftable_new_reader(&reader, &source, "filename"); - EXPECT_ERR(err); - - /* - * Seeking the last ref should work as expected. - */ - reftable_reader_init_ref_iterator(reader, &it); - err = reftable_iterator_seek_ref(&it, "refs/heads/199"); - EXPECT_ERR(err); - - reftable_iterator_destroy(&it); - reftable_writer_free(writer); - reftable_reader_free(reader); - strbuf_release(&writer_buf); - strbuf_release(&buf); -} - -static void test_corrupt_table_empty(void) -{ - struct strbuf buf = STRBUF_INIT; - struct reftable_block_source source = { NULL }; - struct reftable_reader rd = { NULL }; - int err; - - block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); - EXPECT(err == REFTABLE_FORMAT_ERROR); -} - -static void test_corrupt_table(void) -{ - uint8_t zeros[1024] = { 0 }; - struct strbuf buf = STRBUF_INIT; - struct reftable_block_source source = { NULL }; - struct reftable_reader rd = { NULL }; - int err; - strbuf_add(&buf, zeros, sizeof(zeros)); - - block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); - EXPECT(err == REFTABLE_FORMAT_ERROR); - strbuf_release(&buf); -} - -int readwrite_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_log_zlib_corruption); - RUN_TEST(test_corrupt_table); - RUN_TEST(test_corrupt_table_empty); - RUN_TEST(test_log_write_read); - RUN_TEST(test_write_key_order); - RUN_TEST(test_table_read_write_seek_linear_sha256); - RUN_TEST(test_log_buffer_size); - RUN_TEST(test_table_write_small_table); - RUN_TEST(test_buffer); - RUN_TEST(test_table_read_api); - RUN_TEST(test_table_read_write_sequential); - RUN_TEST(test_table_read_write_seek_linear); - RUN_TEST(test_table_read_write_seek_index); - RUN_TEST(test_table_refs_for_no_index); - RUN_TEST(test_table_refs_for_obj_index); - RUN_TEST(test_write_empty_key); - RUN_TEST(test_write_empty_table); - RUN_TEST(test_log_overflow); - RUN_TEST(test_write_object_id_length); - RUN_TEST(test_write_object_id_min_length); - RUN_TEST(test_write_multiple_indices); - RUN_TEST(test_write_multi_level_index); - return 0; -} diff --git a/reftable/record.c b/reftable/record.c index a2cba5ef74..fb5652ed57 100644 --- a/reftable/record.c +++ b/reftable/record.c @@ -98,19 +98,24 @@ const unsigned char *reftable_ref_record_val2(const struct reftable_ref_record * } } -static int decode_string(struct strbuf *dest, struct string_view in) +static int decode_string(struct reftable_buf *dest, struct string_view in) { int start_len = in.len; uint64_t tsize = 0; - int n = get_var_int(&tsize, &in); + int n, err; + + n = get_var_int(&tsize, &in); if (n <= 0) return -1; string_view_consume(&in, n); if (in.len < tsize) return -1; - strbuf_reset(dest); - strbuf_add(dest, in.buf, tsize); + reftable_buf_reset(dest); + err = reftable_buf_add(dest, in.buf, tsize); + if (err < 0) + return err; + string_view_consume(&in, tsize); return start_len - in.len; @@ -133,7 +138,7 @@ static int encode_string(const char *str, struct string_view s) } int reftable_encode_key(int *restart, struct string_view dest, - struct strbuf prev_key, struct strbuf key, + struct reftable_buf prev_key, struct reftable_buf key, uint8_t extra) { struct string_view start = dest; @@ -183,13 +188,13 @@ int reftable_decode_keylen(struct string_view in, return start_len - in.len; } -int reftable_decode_key(struct strbuf *last_key, uint8_t *extra, +int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra, struct string_view in) { int start_len = in.len; uint64_t prefix_len = 0; uint64_t suffix_len = 0; - int n; + int err, n; n = reftable_decode_keylen(in, &prefix_len, &suffix_len, extra); if (n < 0) @@ -200,28 +205,35 @@ int reftable_decode_key(struct strbuf *last_key, uint8_t *extra, prefix_len > last_key->len) return -1; - strbuf_setlen(last_key, prefix_len); - strbuf_add(last_key, in.buf, suffix_len); + err = reftable_buf_setlen(last_key, prefix_len); + if (err < 0) + return err; + + err = reftable_buf_add(last_key, in.buf, suffix_len); + if (err < 0) + return err; + string_view_consume(&in, suffix_len); return start_len - in.len; } -static void reftable_ref_record_key(const void *r, struct strbuf *dest) +static int reftable_ref_record_key(const void *r, struct reftable_buf *dest) { const struct reftable_ref_record *rec = (const struct reftable_ref_record *)r; - strbuf_reset(dest); - strbuf_addstr(dest, rec->refname); + reftable_buf_reset(dest); + return reftable_buf_addstr(dest, rec->refname); } -static void reftable_ref_record_copy_from(void *rec, const void *src_rec, - int hash_size) +static int reftable_ref_record_copy_from(void *rec, const void *src_rec, + int hash_size) { struct reftable_ref_record *ref = rec; const struct reftable_ref_record *src = src_rec; char *refname = NULL; size_t refname_cap = 0; + int err; assert(hash_size > 0); @@ -236,6 +248,11 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec, REFTABLE_ALLOC_GROW(ref->refname, refname_len + 1, ref->refname_cap); + if (!ref->refname) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + memcpy(ref->refname, src->refname, refname_len); ref->refname[refname_len] = 0; } @@ -254,61 +271,17 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec, src->value.val2.target_value, hash_size); break; case REFTABLE_REF_SYMREF: - ref->value.symref = xstrdup(src->value.symref); - break; - } -} - -static char hexdigit(int c) -{ - if (c <= 9) - return '0' + c; - return 'a' + (c - 10); -} - -static void hex_format(char *dest, const unsigned char *src, int hash_size) -{ - assert(hash_size > 0); - if (src) { - int i = 0; - for (i = 0; i < hash_size; i++) { - dest[2 * i] = hexdigit(src[i] >> 4); - dest[2 * i + 1] = hexdigit(src[i] & 0xf); + ref->value.symref = reftable_strdup(src->value.symref); + if (!ref->value.symref) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; } - dest[2 * hash_size] = 0; - } -} - -static void reftable_ref_record_print_sz(const struct reftable_ref_record *ref, - int hash_size) -{ - char hex[GIT_MAX_HEXSZ + 1] = { 0 }; /* BUG */ - printf("ref{%s(%" PRIu64 ") ", ref->refname, ref->update_index); - switch (ref->value_type) { - case REFTABLE_REF_SYMREF: - printf("=> %s", ref->value.symref); - break; - case REFTABLE_REF_VAL2: - hex_format(hex, ref->value.val2.value, hash_size); - printf("val 2 %s", hex); - hex_format(hex, ref->value.val2.target_value, - hash_size); - printf("(T %s)", hex); - break; - case REFTABLE_REF_VAL1: - hex_format(hex, ref->value.val1, hash_size); - printf("val 1 %s", hex); - break; - case REFTABLE_REF_DELETION: - printf("delete"); break; } - printf("}\n"); -} -void reftable_ref_record_print(const struct reftable_ref_record *ref, - uint32_t hash_id) { - reftable_ref_record_print_sz(ref, hash_size(hash_id)); + err = 0; +out: + return err; } static void reftable_ref_record_release_void(void *rec) @@ -388,16 +361,16 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s, return start.len - s.len; } -static int reftable_ref_record_decode(void *rec, struct strbuf key, +static int reftable_ref_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size, struct strbuf *scratch) + int hash_size, struct reftable_buf *scratch) { struct reftable_ref_record *r = rec; struct string_view start = in; uint64_t update_index = 0; const char *refname = NULL; size_t refname_cap = 0; - int n; + int n, err; assert(hash_size > 0); @@ -413,6 +386,10 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, SWAP(r->refname_cap, refname_cap); REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap); + if (!r->refname) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } memcpy(r->refname, key.buf, key.len); r->refname[key.len] = 0; @@ -421,7 +398,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, switch (val_type) { case REFTABLE_REF_VAL1: if (in.len < hash_size) { - return -1; + err = REFTABLE_FORMAT_ERROR; + goto done; } memcpy(r->value.val1, in.buf, hash_size); @@ -430,7 +408,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, case REFTABLE_REF_VAL2: if (in.len < 2 * hash_size) { - return -1; + err = REFTABLE_FORMAT_ERROR; + goto done; } memcpy(r->value.val2.value, in.buf, hash_size); @@ -443,10 +422,11 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, case REFTABLE_REF_SYMREF: { int n = decode_string(scratch, in); if (n < 0) { - return -1; + err = REFTABLE_FORMAT_ERROR; + goto done; } string_view_consume(&in, n); - r->value.symref = strbuf_detach(scratch, NULL); + r->value.symref = reftable_buf_detach(scratch); } break; case REFTABLE_REF_DELETION: @@ -457,6 +437,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, } return start.len - in.len; + +done: + return err; } static int reftable_ref_record_is_deletion_void(const void *p) @@ -480,12 +463,6 @@ static int reftable_ref_record_cmp_void(const void *_a, const void *_b) return strcmp(a->refname, b->refname); } -static void reftable_ref_record_print_void(const void *rec, - int hash_size) -{ - reftable_ref_record_print_sz((struct reftable_ref_record *) rec, hash_size); -} - static struct reftable_record_vtable reftable_ref_record_vtable = { .key = &reftable_ref_record_key, .type = BLOCK_TYPE_REF, @@ -497,57 +474,46 @@ static struct reftable_record_vtable reftable_ref_record_vtable = { .is_deletion = &reftable_ref_record_is_deletion_void, .equal = &reftable_ref_record_equal_void, .cmp = &reftable_ref_record_cmp_void, - .print = &reftable_ref_record_print_void, }; -static void reftable_obj_record_key(const void *r, struct strbuf *dest) +static int reftable_obj_record_key(const void *r, struct reftable_buf *dest) { const struct reftable_obj_record *rec = (const struct reftable_obj_record *)r; - strbuf_reset(dest); - strbuf_add(dest, rec->hash_prefix, rec->hash_prefix_len); + reftable_buf_reset(dest); + return reftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len); } static void reftable_obj_record_release(void *rec) { struct reftable_obj_record *obj = rec; - FREE_AND_NULL(obj->hash_prefix); - FREE_AND_NULL(obj->offsets); + REFTABLE_FREE_AND_NULL(obj->hash_prefix); + REFTABLE_FREE_AND_NULL(obj->offsets); memset(obj, 0, sizeof(struct reftable_obj_record)); } -static void reftable_obj_record_print(const void *rec, int hash_size) -{ - const struct reftable_obj_record *obj = rec; - char hex[GIT_MAX_HEXSZ + 1] = { 0 }; - struct strbuf offset_str = STRBUF_INIT; - int i; - - for (i = 0; i < obj->offset_len; i++) - strbuf_addf(&offset_str, "%" PRIu64 " ", obj->offsets[i]); - hex_format(hex, obj->hash_prefix, obj->hash_prefix_len); - printf("prefix %s (len %d), offsets [%s]\n", - hex, obj->hash_prefix_len, offset_str.buf); - strbuf_release(&offset_str); -} - -static void reftable_obj_record_copy_from(void *rec, const void *src_rec, - int hash_size) +static int reftable_obj_record_copy_from(void *rec, const void *src_rec, + int hash_size UNUSED) { struct reftable_obj_record *obj = rec; - const struct reftable_obj_record *src = - (const struct reftable_obj_record *)src_rec; + const struct reftable_obj_record *src = src_rec; reftable_obj_record_release(obj); REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len); + if (!obj->hash_prefix) + return REFTABLE_OUT_OF_MEMORY_ERROR; obj->hash_prefix_len = src->hash_prefix_len; if (src->hash_prefix_len) memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len); REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len); + if (!obj->offsets) + return REFTABLE_OUT_OF_MEMORY_ERROR; obj->offset_len = src->offset_len; COPY_ARRAY(obj->offsets, src->offsets, src->offset_len); + + return 0; } static uint8_t reftable_obj_record_val_type(const void *rec) @@ -559,7 +525,7 @@ static uint8_t reftable_obj_record_val_type(const void *rec) } static int reftable_obj_record_encode(const void *rec, struct string_view s, - int hash_size) + int hash_size UNUSED) { const struct reftable_obj_record *r = rec; struct string_view start = s; @@ -592,9 +558,10 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s, return start.len - s.len; } -static int reftable_obj_record_decode(void *rec, struct strbuf key, +static int reftable_obj_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size, struct strbuf *scratch UNUSED) + int hash_size UNUSED, + struct reftable_buf *scratch UNUSED) { struct string_view start = in; struct reftable_obj_record *r = rec; @@ -606,6 +573,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key, reftable_obj_record_release(r); REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len); + if (!r->hash_prefix) + return REFTABLE_OUT_OF_MEMORY_ERROR; memcpy(r->hash_prefix, key.buf, key.len); r->hash_prefix_len = key.len; @@ -624,6 +593,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key, return start.len - in.len; REFTABLE_ALLOC_ARRAY(r->offsets, count); + if (!r->offsets) + return REFTABLE_OUT_OF_MEMORY_ERROR; r->offset_len = count; n = get_var_int(&r->offsets[0], &in); @@ -647,12 +618,13 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key, return start.len - in.len; } -static int not_a_deletion(const void *p) +static int not_a_deletion(const void *p UNUSED) { return 0; } -static int reftable_obj_record_equal_void(const void *a, const void *b, int hash_size) +static int reftable_obj_record_equal_void(const void *a, const void *b, + int hash_size UNUSED) { struct reftable_obj_record *ra = (struct reftable_obj_record *) a; struct reftable_obj_record *rb = (struct reftable_obj_record *) b; @@ -701,83 +673,69 @@ static struct reftable_record_vtable reftable_obj_record_vtable = { .is_deletion = ¬_a_deletion, .equal = &reftable_obj_record_equal_void, .cmp = &reftable_obj_record_cmp_void, - .print = &reftable_obj_record_print, }; -static void reftable_log_record_print_sz(struct reftable_log_record *log, - int hash_size) -{ - char hex[GIT_MAX_HEXSZ + 1] = { 0 }; - - switch (log->value_type) { - case REFTABLE_LOG_DELETION: - printf("log{%s(%" PRIu64 ") delete\n", log->refname, - log->update_index); - break; - case REFTABLE_LOG_UPDATE: - printf("log{%s(%" PRIu64 ") %s <%s> %" PRIu64 " %04d\n", - log->refname, log->update_index, - log->value.update.name ? log->value.update.name : "", - log->value.update.email ? log->value.update.email : "", - log->value.update.time, - log->value.update.tz_offset); - hex_format(hex, log->value.update.old_hash, hash_size); - printf("%s => ", hex); - hex_format(hex, log->value.update.new_hash, hash_size); - printf("%s\n\n%s\n}\n", hex, - log->value.update.message ? log->value.update.message : ""); - break; - } -} - -void reftable_log_record_print(struct reftable_log_record *log, - uint32_t hash_id) -{ - reftable_log_record_print_sz(log, hash_size(hash_id)); -} - -static void reftable_log_record_key(const void *r, struct strbuf *dest) +static int reftable_log_record_key(const void *r, struct reftable_buf *dest) { const struct reftable_log_record *rec = (const struct reftable_log_record *)r; - int len = strlen(rec->refname); + int len = strlen(rec->refname), err; uint8_t i64[8]; uint64_t ts = 0; - strbuf_reset(dest); - strbuf_add(dest, (uint8_t *)rec->refname, len + 1); + + reftable_buf_reset(dest); + err = reftable_buf_add(dest, (uint8_t *)rec->refname, len + 1); + if (err < 0) + return err; ts = (~ts) - rec->update_index; put_be64(&i64[0], ts); - strbuf_add(dest, i64, sizeof(i64)); + + err = reftable_buf_add(dest, i64, sizeof(i64)); + if (err < 0) + return err; + + return 0; } -static void reftable_log_record_copy_from(void *rec, const void *src_rec, - int hash_size) +static int reftable_log_record_copy_from(void *rec, const void *src_rec, + int hash_size) { struct reftable_log_record *dst = rec; const struct reftable_log_record *src = (const struct reftable_log_record *)src_rec; + int ret; reftable_log_record_release(dst); *dst = *src; + if (dst->refname) { - dst->refname = xstrdup(dst->refname); + dst->refname = reftable_strdup(dst->refname); + if (!dst->refname) { + ret = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } } + switch (dst->value_type) { case REFTABLE_LOG_DELETION: break; case REFTABLE_LOG_UPDATE: - if (dst->value.update.email) { + if (dst->value.update.email) dst->value.update.email = - xstrdup(dst->value.update.email); - } - if (dst->value.update.name) { + reftable_strdup(dst->value.update.email); + if (dst->value.update.name) dst->value.update.name = - xstrdup(dst->value.update.name); - } - if (dst->value.update.message) { + reftable_strdup(dst->value.update.name); + if (dst->value.update.message) dst->value.update.message = - xstrdup(dst->value.update.message); + reftable_strdup(dst->value.update.message); + + if (!dst->value.update.email || + !dst->value.update.name || + !dst->value.update.message) { + ret = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; } memcpy(dst->value.update.new_hash, @@ -786,6 +744,10 @@ static void reftable_log_record_copy_from(void *rec, const void *src_rec, src->value.update.old_hash, hash_size); break; } + + ret = 0; +out: + return ret; } static void reftable_log_record_release_void(void *rec) @@ -864,20 +826,25 @@ static int reftable_log_record_encode(const void *rec, struct string_view s, return start.len - s.len; } -static int reftable_log_record_decode(void *rec, struct strbuf key, +static int reftable_log_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - int hash_size, struct strbuf *scratch) + int hash_size, struct reftable_buf *scratch) { struct string_view start = in; struct reftable_log_record *r = rec; uint64_t max = 0; uint64_t ts = 0; - int n; + int err, n; if (key.len <= 9 || key.buf[key.len - 9] != 0) return REFTABLE_FORMAT_ERROR; REFTABLE_ALLOC_GROW(r->refname, key.len - 8, r->refname_cap); + if (!r->refname) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + memcpy(r->refname, key.buf, key.len - 8); ts = get_be64(key.buf + key.len - 8); @@ -886,10 +853,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, if (val_type != r->value_type) { switch (r->value_type) { case REFTABLE_LOG_UPDATE: - FREE_AND_NULL(r->value.update.message); + REFTABLE_FREE_AND_NULL(r->value.update.message); r->value.update.message_cap = 0; - FREE_AND_NULL(r->value.update.email); - FREE_AND_NULL(r->value.update.name); + REFTABLE_FREE_AND_NULL(r->value.update.email); + REFTABLE_FREE_AND_NULL(r->value.update.name); break; case REFTABLE_LOG_DELETION: break; @@ -900,8 +867,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, if (val_type == REFTABLE_LOG_DELETION) return 0; - if (in.len < 2 * hash_size) - return REFTABLE_FORMAT_ERROR; + if (in.len < 2 * hash_size) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } memcpy(r->value.update.old_hash, in.buf, hash_size); memcpy(r->value.update.new_hash, in.buf + hash_size, hash_size); @@ -909,8 +878,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, string_view_consume(&in, 2 * hash_size); n = decode_string(scratch, in); - if (n < 0) + if (n < 0) { + err = REFTABLE_FORMAT_ERROR; goto done; + } string_view_consume(&in, n); /* @@ -921,52 +892,75 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, */ if (!r->value.update.name || strcmp(r->value.update.name, scratch->buf)) { - r->value.update.name = - reftable_realloc(r->value.update.name, scratch->len + 1); + char *name = reftable_realloc(r->value.update.name, scratch->len + 1); + if (!name) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + + r->value.update.name = name; memcpy(r->value.update.name, scratch->buf, scratch->len); r->value.update.name[scratch->len] = 0; } n = decode_string(scratch, in); - if (n < 0) + if (n < 0) { + err = REFTABLE_FORMAT_ERROR; goto done; + } string_view_consume(&in, n); /* Same as above, but for the reflog email. */ if (!r->value.update.email || strcmp(r->value.update.email, scratch->buf)) { - r->value.update.email = - reftable_realloc(r->value.update.email, scratch->len + 1); + char *email = reftable_realloc(r->value.update.email, scratch->len + 1); + if (!email) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + + r->value.update.email = email; memcpy(r->value.update.email, scratch->buf, scratch->len); r->value.update.email[scratch->len] = 0; } ts = 0; n = get_var_int(&ts, &in); - if (n < 0) + if (n < 0) { + err = REFTABLE_FORMAT_ERROR; goto done; + } string_view_consume(&in, n); r->value.update.time = ts; - if (in.len < 2) + if (in.len < 2) { + err = REFTABLE_FORMAT_ERROR; goto done; + } r->value.update.tz_offset = get_be16(in.buf); string_view_consume(&in, 2); n = decode_string(scratch, in); - if (n < 0) + if (n < 0) { + err = REFTABLE_FORMAT_ERROR; goto done; + } string_view_consume(&in, n); REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1, r->value.update.message_cap); + if (!r->value.update.message) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + memcpy(r->value.update.message, scratch->buf, scratch->len); r->value.update.message[scratch->len] = 0; return start.len - in.len; done: - return REFTABLE_FORMAT_ERROR; + return err; } static int null_streq(const char *a, const char *b) @@ -1039,11 +1033,6 @@ static int reftable_log_record_is_deletion_void(const void *p) (const struct reftable_log_record *)p); } -static void reftable_log_record_print_void(const void *rec, int hash_size) -{ - reftable_log_record_print_sz((struct reftable_log_record*)rec, hash_size); -} - static struct reftable_record_vtable reftable_log_record_vtable = { .key = &reftable_log_record_key, .type = BLOCK_TYPE_LOG, @@ -1055,40 +1044,44 @@ static struct reftable_record_vtable reftable_log_record_vtable = { .is_deletion = &reftable_log_record_is_deletion_void, .equal = &reftable_log_record_equal_void, .cmp = &reftable_log_record_cmp_void, - .print = &reftable_log_record_print_void, }; -static void reftable_index_record_key(const void *r, struct strbuf *dest) +static int reftable_index_record_key(const void *r, struct reftable_buf *dest) { const struct reftable_index_record *rec = r; - strbuf_reset(dest); - strbuf_addbuf(dest, &rec->last_key); + reftable_buf_reset(dest); + return reftable_buf_add(dest, rec->last_key.buf, rec->last_key.len); } -static void reftable_index_record_copy_from(void *rec, const void *src_rec, - int hash_size) +static int reftable_index_record_copy_from(void *rec, const void *src_rec, + int hash_size UNUSED) { struct reftable_index_record *dst = rec; const struct reftable_index_record *src = src_rec; + int err; - strbuf_reset(&dst->last_key); - strbuf_addbuf(&dst->last_key, &src->last_key); + reftable_buf_reset(&dst->last_key); + err = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len); + if (err < 0) + return err; dst->offset = src->offset; + + return 0; } static void reftable_index_record_release(void *rec) { struct reftable_index_record *idx = rec; - strbuf_release(&idx->last_key); + reftable_buf_release(&idx->last_key); } -static uint8_t reftable_index_record_val_type(const void *rec) +static uint8_t reftable_index_record_val_type(const void *rec UNUSED) { return 0; } static int reftable_index_record_encode(const void *rec, struct string_view out, - int hash_size) + int hash_size UNUSED) { const struct reftable_index_record *r = (const struct reftable_index_record *)rec; @@ -1103,16 +1096,20 @@ static int reftable_index_record_encode(const void *rec, struct string_view out, return start.len - out.len; } -static int reftable_index_record_decode(void *rec, struct strbuf key, - uint8_t val_type, struct string_view in, - int hash_size, struct strbuf *scratch UNUSED) +static int reftable_index_record_decode(void *rec, struct reftable_buf key, + uint8_t val_type UNUSED, + struct string_view in, + int hash_size UNUSED, + struct reftable_buf *scratch UNUSED) { struct string_view start = in; struct reftable_index_record *r = rec; - int n = 0; + int err, n = 0; - strbuf_reset(&r->last_key); - strbuf_addbuf(&r->last_key, &key); + reftable_buf_reset(&r->last_key); + err = reftable_buf_add(&r->last_key, key.buf, key.len); + if (err < 0) + return err; n = get_var_int(&r->offset, &in); if (n < 0) @@ -1122,26 +1119,20 @@ static int reftable_index_record_decode(void *rec, struct strbuf key, return start.len - in.len; } -static int reftable_index_record_equal(const void *a, const void *b, int hash_size) +static int reftable_index_record_equal(const void *a, const void *b, + int hash_size UNUSED) { struct reftable_index_record *ia = (struct reftable_index_record *) a; struct reftable_index_record *ib = (struct reftable_index_record *) b; - return ia->offset == ib->offset && !strbuf_cmp(&ia->last_key, &ib->last_key); + return ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key); } static int reftable_index_record_cmp(const void *_a, const void *_b) { const struct reftable_index_record *a = _a; const struct reftable_index_record *b = _b; - return strbuf_cmp(&a->last_key, &b->last_key); -} - -static void reftable_index_record_print(const void *rec, int hash_size) -{ - const struct reftable_index_record *idx = rec; - /* TODO: escape null chars? */ - printf("\"%s\" %" PRIu64 "\n", idx->last_key.buf, idx->offset); + return reftable_buf_cmp(&a->last_key, &b->last_key); } static struct reftable_record_vtable reftable_index_record_vtable = { @@ -1155,12 +1146,11 @@ static struct reftable_record_vtable reftable_index_record_vtable = { .is_deletion = ¬_a_deletion, .equal = &reftable_index_record_equal, .cmp = &reftable_index_record_cmp, - .print = &reftable_index_record_print, }; -void reftable_record_key(struct reftable_record *rec, struct strbuf *dest) +int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest) { - reftable_record_vtable(rec)->key(reftable_record_data(rec), dest); + return reftable_record_vtable(rec)->key(reftable_record_data(rec), dest); } int reftable_record_encode(struct reftable_record *rec, struct string_view dest, @@ -1170,14 +1160,14 @@ int reftable_record_encode(struct reftable_record *rec, struct string_view dest, dest, hash_size); } -void reftable_record_copy_from(struct reftable_record *rec, +int reftable_record_copy_from(struct reftable_record *rec, struct reftable_record *src, int hash_size) { assert(src->type == rec->type); - reftable_record_vtable(rec)->copy_from(reftable_record_data(rec), - reftable_record_data(src), - hash_size); + return reftable_record_vtable(rec)->copy_from(reftable_record_data(rec), + reftable_record_data(src), + hash_size); } uint8_t reftable_record_val_type(struct reftable_record *rec) @@ -1185,9 +1175,9 @@ uint8_t reftable_record_val_type(struct reftable_record *rec) return reftable_record_vtable(rec)->val_type(reftable_record_data(rec)); } -int reftable_record_decode(struct reftable_record *rec, struct strbuf key, +int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key, uint8_t extra, struct string_view src, int hash_size, - struct strbuf *scratch) + struct reftable_buf *scratch) { return reftable_record_vtable(rec)->decode(reftable_record_data(rec), key, extra, src, hash_size, @@ -1328,15 +1318,9 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ) case BLOCK_TYPE_OBJ: return; case BLOCK_TYPE_INDEX: - strbuf_init(&rec->u.idx.last_key, 0); + reftable_buf_init(&rec->u.idx.last_key); return; default: BUG("unhandled record type"); } } - -void reftable_record_print(struct reftable_record *rec, int hash_size) -{ - printf("'%c': ", rec->type); - reftable_record_vtable(rec)->print(reftable_record_data(rec), hash_size); -} diff --git a/reftable/record.h b/reftable/record.h index d778133e6e..25aa908c85 100644 --- a/reftable/record.h +++ b/reftable/record.h @@ -9,6 +9,7 @@ https://developers.google.com/open-source/licenses/bsd #ifndef RECORD_H #define RECORD_H +#include "basics.h" #include "system.h" #include <stdint.h> @@ -38,13 +39,13 @@ int put_var_int(struct string_view *dest, uint64_t val); /* Methods for records. */ struct reftable_record_vtable { - /* encode the key of to a uint8_t strbuf. */ - void (*key)(const void *rec, struct strbuf *dest); + /* encode the key of to a uint8_t reftable_buf. */ + int (*key)(const void *rec, struct reftable_buf *dest); /* The record type of ('r' for ref). */ uint8_t type; - void (*copy_from)(void *dest, const void *src, int hash_size); + int (*copy_from)(void *dest, const void *src, int hash_size); /* a value of [0..7], indicating record subvariants (eg. ref vs. symref * vs ref deletion) */ @@ -54,9 +55,9 @@ struct reftable_record_vtable { int (*encode)(const void *rec, struct string_view dest, int hash_size); /* decode data from `src` into the record. */ - int (*decode)(void *rec, struct strbuf key, uint8_t extra, + int (*decode)(void *rec, struct reftable_buf key, uint8_t extra, struct string_view src, int hash_size, - struct strbuf *scratch); + struct reftable_buf *scratch); /* deallocate and null the record. */ void (*release)(void *rec); @@ -83,7 +84,7 @@ int reftable_is_block_type(uint8_t typ); /* Encode `key` into `dest`. Sets `is_restart` to indicate a restart. Returns * number of bytes written. */ int reftable_encode_key(int *is_restart, struct string_view dest, - struct strbuf prev_key, struct strbuf key, + struct reftable_buf prev_key, struct reftable_buf key, uint8_t extra); /* Decode a record's key lengths. */ @@ -96,13 +97,13 @@ int reftable_decode_keylen(struct string_view in, * Decode into `last_key` and `extra` from `in`. `last_key` is expected to * contain the decoded key of the preceding record, if any. */ -int reftable_decode_key(struct strbuf *last_key, uint8_t *extra, +int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra, struct string_view in); /* reftable_index_record are used internally to speed up lookups. */ struct reftable_index_record { uint64_t offset; /* Offset of block */ - struct strbuf last_key; /* Last key of the block. */ + struct reftable_buf last_key; /* Last key of the block. */ }; /* reftable_obj_record stores an object ID => ref mapping. */ @@ -136,16 +137,15 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ); /* see struct record_vtable */ int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b); int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size); -void reftable_record_print(struct reftable_record *rec, int hash_size); -void reftable_record_key(struct reftable_record *rec, struct strbuf *dest); -void reftable_record_copy_from(struct reftable_record *rec, - struct reftable_record *src, int hash_size); +int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest); +int reftable_record_copy_from(struct reftable_record *rec, + struct reftable_record *src, int hash_size); uint8_t reftable_record_val_type(struct reftable_record *rec); int reftable_record_encode(struct reftable_record *rec, struct string_view dest, int hash_size); -int reftable_record_decode(struct reftable_record *rec, struct strbuf key, +int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key, uint8_t extra, struct string_view src, - int hash_size, struct strbuf *scratch); + int hash_size, struct reftable_buf *scratch); int reftable_record_is_deletion(struct reftable_record *rec); static inline uint8_t reftable_record_type(struct reftable_record *rec) diff --git a/reftable/reftable-basics.h b/reftable/reftable-basics.h new file mode 100644 index 0000000000..e0397ed583 --- /dev/null +++ b/reftable/reftable-basics.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd +*/ + +#ifndef REFTABLE_BASICS_H +#define REFTABLE_BASICS_H + +#include <stddef.h> + +/* + * Hash functions understood by the reftable library. Note that the values are + * arbitrary and somewhat random such that we can easily detect cases where the + * hash hasn't been properly set up. + */ +enum reftable_hash { + REFTABLE_HASH_SHA1 = 89, + REFTABLE_HASH_SHA256 = 247, +}; +#define REFTABLE_HASH_SIZE_SHA1 20 +#define REFTABLE_HASH_SIZE_SHA256 32 +#define REFTABLE_HASH_SIZE_MAX REFTABLE_HASH_SIZE_SHA256 + +/* Overrides the functions to use for memory management. */ +void reftable_set_alloc(void *(*malloc)(size_t), + void *(*realloc)(void *, size_t), void (*free)(void *)); + +#endif diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h index 6368cd9ed9..f404826562 100644 --- a/reftable/reftable-error.h +++ b/reftable/reftable-error.h @@ -57,6 +57,9 @@ enum reftable_error { /* Trying to write out-of-date data. */ REFTABLE_OUTDATED_ERROR = -12, + + /* An allocation has failed due to an out-of-memory situation. */ + REFTABLE_OUT_OF_MEMORY_ERROR = -13, }; /* convert the numeric error code to a string. The string should not be diff --git a/reftable/reftable-generic.h b/reftable/reftable-generic.h deleted file mode 100644 index 65670ea093..0000000000 --- a/reftable/reftable-generic.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef REFTABLE_GENERIC_H -#define REFTABLE_GENERIC_H - -#include "reftable-iterator.h" - -struct reftable_table_vtable; - -/* - * Provides a unified API for reading tables, either merged tables, or single - * readers. */ -struct reftable_table { - struct reftable_table_vtable *ops; - void *table_arg; -}; - -void reftable_table_init_ref_iter(struct reftable_table *tab, - struct reftable_iterator *it); - -void reftable_table_init_log_iter(struct reftable_table *tab, - struct reftable_iterator *it); - -/* returns the hash ID from a generic reftable_table */ -uint32_t reftable_table_hash_id(struct reftable_table *tab); - -/* returns the max update_index covered by this table. */ -uint64_t reftable_table_max_update_index(struct reftable_table *tab); - -/* returns the min update_index covered by this table. */ -uint64_t reftable_table_min_update_index(struct reftable_table *tab); - -/* convenience function to read a single ref. Returns < 0 for error, 0 - for success, and 1 if ref not found. */ -int reftable_table_read_ref(struct reftable_table *tab, const char *name, - struct reftable_ref_record *ref); - -/* dump table contents onto stdout for debugging */ -int reftable_table_print(struct reftable_table *tab); - -#endif diff --git a/reftable/reftable-malloc.h b/reftable/reftable-malloc.h deleted file mode 100644 index 5f2185f1f3..0000000000 --- a/reftable/reftable-malloc.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef REFTABLE_H -#define REFTABLE_H - -#include <stddef.h> - -/* Overrides the functions to use for memory management. */ -void reftable_set_alloc(void *(*malloc)(size_t), - void *(*realloc)(void *, size_t), void (*free)(void *)); - -#endif diff --git a/reftable/reftable-merged.h b/reftable/reftable-merged.h index 14d5fc9f05..f2d01c3ef8 100644 --- a/reftable/reftable-merged.h +++ b/reftable/reftable-merged.h @@ -26,15 +26,23 @@ https://developers.google.com/open-source/licenses/bsd /* A merged table is implements seeking/iterating over a stack of tables. */ struct reftable_merged_table; -/* A generic reftable; see below. */ -struct reftable_table; +struct reftable_reader; -/* reftable_new_merged_table creates a new merged table. It takes ownership of - the stack array. -*/ -int reftable_new_merged_table(struct reftable_merged_table **dest, - struct reftable_table *stack, size_t n, - uint32_t hash_id); +/* + * reftable_merged_table_new creates a new merged table. The readers must be + * kept alive as long as the merged table is still in use. + */ +int reftable_merged_table_new(struct reftable_merged_table **dest, + struct reftable_reader **readers, size_t n, + enum reftable_hash hash_id); + +/* Initialize a merged table iterator for reading refs. */ +int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, + struct reftable_iterator *it); + +/* Initialize a merged table iterator for reading logs. */ +int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, + struct reftable_iterator *it); /* returns the max update_index covered by this merged table. */ uint64_t @@ -48,10 +56,6 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt); void reftable_merged_table_free(struct reftable_merged_table *m); /* return the hash ID of the merged table. */ -uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *m); - -/* create a generic table from reftable_merged_table */ -void reftable_table_from_merged_table(struct reftable_table *tab, - struct reftable_merged_table *table); +enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *m); #endif diff --git a/reftable/reftable-reader.h b/reftable/reftable-reader.h index a32f31d648..0085fbb903 100644 --- a/reftable/reftable-reader.h +++ b/reftable/reftable-reader.h @@ -23,32 +23,38 @@ /* The reader struct is a handle to an open reftable file. */ struct reftable_reader; -/* Generic table. */ -struct reftable_table; - -/* reftable_new_reader opens a reftable for reading. If successful, +/* reftable_reader_new opens a reftable for reading. If successful, * returns 0 code and sets pp. The name is used for creating a * stack. Typically, it is the basename of the file. The block source * `src` is owned by the reader, and is closed on calling * reftable_reader_destroy(). On error, the block source `src` is * closed as well. */ -int reftable_new_reader(struct reftable_reader **pp, +int reftable_reader_new(struct reftable_reader **pp, struct reftable_block_source *src, const char *name); +/* + * Manage the reference count of the reftable reader. A newly initialized + * reader starts with a refcount of 1 and will be deleted once the refcount has + * reached 0. + * + * This is required because readers may have longer lifetimes than the stack + * they belong to. The stack may for example be reloaded while the old tables + * are still being accessed by an iterator. + */ +void reftable_reader_incref(struct reftable_reader *reader); +void reftable_reader_decref(struct reftable_reader *reader); + /* Initialize a reftable iterator for reading refs. */ -void reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it); +int reftable_reader_init_ref_iterator(struct reftable_reader *r, + struct reftable_iterator *it); /* Initialize a reftable iterator for reading logs. */ -void reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it); +int reftable_reader_init_log_iterator(struct reftable_reader *r, + struct reftable_iterator *it); /* returns the hash ID used in this table. */ -uint32_t reftable_reader_hash_id(struct reftable_reader *r); - -/* closes and deallocates a reader. */ -void reftable_reader_free(struct reftable_reader *); +enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r); /* return an iterator for the refs pointing to `oid`. */ int reftable_reader_refs_for(struct reftable_reader *r, @@ -60,12 +66,6 @@ uint64_t reftable_reader_max_update_index(struct reftable_reader *r); /* return the min_update_index for a table */ uint64_t reftable_reader_min_update_index(struct reftable_reader *r); -/* creates a generic table from a file reader. */ -void reftable_table_from_reader(struct reftable_table *tab, - struct reftable_reader *reader); - -/* print table onto stdout for debugging. */ -int reftable_reader_print_file(const char *tablename); /* print blocks onto stdout for debugging. */ int reftable_reader_print_blocks(const char *tablename); diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h index ff486eb1f7..ddd48eb579 100644 --- a/reftable/reftable-record.h +++ b/reftable/reftable-record.h @@ -9,7 +9,7 @@ https://developers.google.com/open-source/licenses/bsd #ifndef REFTABLE_RECORD_H #define REFTABLE_RECORD_H -#include "hash.h" +#include "reftable-basics.h" #include <stdint.h> /* @@ -40,10 +40,10 @@ struct reftable_ref_record { #define REFTABLE_NR_REF_VALUETYPES 4 } value_type; union { - unsigned char val1[GIT_MAX_RAWSZ]; + unsigned char val1[REFTABLE_HASH_SIZE_MAX]; struct { - unsigned char value[GIT_MAX_RAWSZ]; /* first hash */ - unsigned char target_value[GIT_MAX_RAWSZ]; /* second hash */ + unsigned char value[REFTABLE_HASH_SIZE_MAX]; /* first hash */ + unsigned char target_value[REFTABLE_HASH_SIZE_MAX]; /* second hash */ } val2; char *symref; /* referent, malloced 0-terminated string */ } value; @@ -60,10 +60,6 @@ const unsigned char *reftable_ref_record_val2(const struct reftable_ref_record * /* returns whether 'ref' represents a deletion */ int reftable_ref_record_is_deletion(const struct reftable_ref_record *ref); -/* prints a reftable_ref_record onto stdout. Useful for debugging. */ -void reftable_ref_record_print(const struct reftable_ref_record *ref, - uint32_t hash_id); - /* frees and nulls all pointer values inside `ref`. */ void reftable_ref_record_release(struct reftable_ref_record *ref); @@ -89,8 +85,8 @@ struct reftable_log_record { union { struct { - unsigned char new_hash[GIT_MAX_RAWSZ]; - unsigned char old_hash[GIT_MAX_RAWSZ]; + unsigned char new_hash[REFTABLE_HASH_SIZE_MAX]; + unsigned char old_hash[REFTABLE_HASH_SIZE_MAX]; char *name; char *email; uint64_t time; @@ -111,8 +107,4 @@ void reftable_log_record_release(struct reftable_log_record *log); int reftable_log_record_equal(const struct reftable_log_record *a, const struct reftable_log_record *b, int hash_size); -/* dumps a reftable_log_record on stdout, for debugging/testing. */ -void reftable_log_record_print(struct reftable_log_record *log, - uint32_t hash_id); - #endif diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h index 09e97c9991..ae14270ea7 100644 --- a/reftable/reftable-stack.h +++ b/reftable/reftable-stack.h @@ -37,12 +37,21 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st); /* holds a transaction to add tables at the top of a stack. */ struct reftable_addition; +enum { + /* + * Reload the stack when the stack is out-of-date after locking it. + */ + REFTABLE_STACK_NEW_ADDITION_RELOAD = (1 << 0), +}; + /* * returns a new transaction to add reftables to the given stack. As a side - * effect, the ref database is locked. + * effect, the ref database is locked. Accepts REFTABLE_STACK_NEW_ADDITION_* + * flags. */ int reftable_stack_new_addition(struct reftable_addition **dest, - struct reftable_stack *st); + struct reftable_stack *st, + unsigned int flags); /* Adds a reftable to transaction. */ int reftable_addition_add(struct reftable_addition *add, @@ -73,16 +82,16 @@ struct reftable_iterator; * be used to iterate through refs. The iterator is valid until the next reload * or write. */ -void reftable_stack_init_ref_iterator(struct reftable_stack *st, - struct reftable_iterator *it); +int reftable_stack_init_ref_iterator(struct reftable_stack *st, + struct reftable_iterator *it); /* * Initialize an iterator for the merged tables contained in the stack that can * be used to iterate through logs. The iterator is valid until the next reload * or write. */ -void reftable_stack_init_log_iterator(struct reftable_stack *st, - struct reftable_iterator *it); +int reftable_stack_init_log_iterator(struct reftable_stack *st, + struct reftable_iterator *it); /* returns the merged_table for seeking. This table is valid until the * next write or reload, and should not be closed or deleted. @@ -140,7 +149,7 @@ struct reftable_compaction_stats { struct reftable_compaction_stats * reftable_stack_compaction_stats(struct reftable_stack *st); -/* print the entire stack represented by the directory */ -int reftable_stack_print_directory(const char *stackdir, uint32_t hash_id); +/* Return the hash of the stack. */ +enum reftable_hash reftable_stack_hash_id(struct reftable_stack *st); #endif diff --git a/reftable/reftable-tests.h b/reftable/reftable-tests.h deleted file mode 100644 index 114cc3d053..0000000000 --- a/reftable/reftable-tests.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef REFTABLE_TESTS_H -#define REFTABLE_TESTS_H - -int basics_test_main(int argc, const char **argv); -int block_test_main(int argc, const char **argv); -int merged_test_main(int argc, const char **argv); -int pq_test_main(int argc, const char **argv); -int record_test_main(int argc, const char **argv); -int readwrite_test_main(int argc, const char **argv); -int stack_test_main(int argc, const char **argv); -int tree_test_main(int argc, const char **argv); -int reftable_dump_main(int argc, char *const *argv); - -#endif diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 189b1f4144..5f9afa620b 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -33,7 +33,7 @@ struct reftable_write_options { /* 4-byte identifier ("sha1", "s256") of the hash. * Defaults to SHA1 if unset */ - uint32_t hash_id; + enum reftable_hash hash_id; /* Default mode for creating files. If unset, use 0666 (+umask) */ unsigned int default_permissions; @@ -51,6 +51,32 @@ struct reftable_write_options { * tables to compact. Defaults to 2 if unset. */ uint8_t auto_compaction_factor; + + /* + * The number of milliseconds to wait when trying to lock "tables.list". + * Note that this does not apply to locking individual tables, as these + * should only ever be locked when already holding the "tables.list" + * lock. + * + * Passing 0 will fail immediately when the file is locked, passing a + * negative value will cause us to block indefinitely. + */ + long lock_timeout_ms; + + /* + * Optional callback used to fsync files to disk. Falls back to using + * fsync(3P) when unset. + */ + int (*fsync)(int fd); + + /* + * Callback function to execute whenever the stack is being reloaded. + * This can be used e.g. to discard cached information that relies on + * the old stack's data. The payload data will be passed as argument to + * the callback. + */ + void (*on_reload)(void *payload); + void *on_reload_payload; }; /* reftable_block_stats holds statistics for a single block type */ @@ -90,11 +116,13 @@ struct reftable_stats { int object_id_len; }; -/* reftable_new_writer creates a new writer */ -struct reftable_writer * -reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t), - int (*flush_func)(void *), - void *writer_arg, const struct reftable_write_options *opts); +struct reftable_writer; + +/* Create a new writer. */ +int reftable_writer_new(struct reftable_writer **out, + ssize_t (*writer_func)(void *, const void *, size_t), + int (*flush_func)(void *), + void *writer_arg, const struct reftable_write_options *opts); /* Set the range of update indices for the records we will add. When writing a table into a stack, the min should be at least diff --git a/reftable/stack.c b/reftable/stack.c index 737591125e..59fd695a12 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -8,17 +8,14 @@ https://developers.google.com/open-source/licenses/bsd #include "stack.h" -#include "../write-or-die.h" #include "system.h" #include "constants.h" #include "merged.h" #include "reader.h" #include "reftable-error.h" -#include "reftable-generic.h" #include "reftable-record.h" #include "reftable-merged.h" #include "writer.h" -#include "tempfile.h" static int stack_try_add(struct reftable_stack *st, int (*write_table)(struct reftable_writer *wr, @@ -32,58 +29,87 @@ static void reftable_addition_close(struct reftable_addition *add); static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, int reuse_open); -static void stack_filename(struct strbuf *dest, struct reftable_stack *st, - const char *name) +static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st, + const char *name) { - strbuf_reset(dest); - strbuf_addstr(dest, st->reftable_dir); - strbuf_addstr(dest, "/"); - strbuf_addstr(dest, name); + int err; + reftable_buf_reset(dest); + if ((err = reftable_buf_addstr(dest, st->reftable_dir)) < 0 || + (err = reftable_buf_addstr(dest, "/")) < 0 || + (err = reftable_buf_addstr(dest, name)) < 0) + return err; + return 0; } -static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz) +static int stack_fsync(const struct reftable_write_options *opts, int fd) { - int *fdp = (int *)arg; - return write_in_full(*fdp, data, sz); + if (opts->fsync) + return opts->fsync(fd); + return fsync(fd); } -static int reftable_fd_flush(void *arg) +struct fd_writer { + const struct reftable_write_options *opts; + int fd; +}; + +static ssize_t fd_writer_write(void *arg, const void *data, size_t sz) { - int *fdp = (int *)arg; + struct fd_writer *writer = arg; + return write_in_full(writer->fd, data, sz); +} - return fsync_component(FSYNC_COMPONENT_REFERENCE, *fdp); +static int fd_writer_flush(void *arg) +{ + struct fd_writer *writer = arg; + return stack_fsync(writer->opts, writer->fd); } int reftable_new_stack(struct reftable_stack **dest, const char *dir, const struct reftable_write_options *_opts) { - struct reftable_stack *p = reftable_calloc(1, sizeof(*p)); - struct strbuf list_file_name = STRBUF_INIT; - struct reftable_write_options opts = {0}; - int err = 0; + struct reftable_buf list_file_name = REFTABLE_BUF_INIT; + struct reftable_write_options opts = { 0 }; + struct reftable_stack *p; + int err; + + p = reftable_calloc(1, sizeof(*p)); + if (!p) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } if (_opts) opts = *_opts; if (opts.hash_id == 0) - opts.hash_id = GIT_SHA1_FORMAT_ID; + opts.hash_id = REFTABLE_HASH_SHA1; *dest = NULL; - strbuf_reset(&list_file_name); - strbuf_addstr(&list_file_name, dir); - strbuf_addstr(&list_file_name, "/tables.list"); + reftable_buf_reset(&list_file_name); + if ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 || + (err = reftable_buf_addstr(&list_file_name, "/tables.list")) < 0) + goto out; - p->list_file = strbuf_detach(&list_file_name, NULL); + p->list_file = reftable_buf_detach(&list_file_name); p->list_fd = -1; - p->reftable_dir = xstrdup(dir); p->opts = opts; + p->reftable_dir = reftable_strdup(dir); + if (!p->reftable_dir) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } err = reftable_stack_reload_maybe_reuse(p, 1); - if (err < 0) { + if (err < 0) + goto out; + + *dest = p; + err = 0; + +out: + if (err < 0) reftable_stack_destroy(p); - } else { - *dest = p; - } return err; } @@ -103,13 +129,22 @@ static int fd_read_lines(int fd, char ***namesp) } REFTABLE_ALLOC_ARRAY(buf, size + 1); + if (!buf) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + if (read_in_full(fd, buf, size) != size) { err = REFTABLE_IO_ERROR; goto done; } buf[size] = 0; - parse_names(buf, size, namesp); + *namesp = parse_names(buf, size); + if (!*namesp) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } done: reftable_free(buf); @@ -123,6 +158,8 @@ int read_lines(const char *filename, char ***namesp) if (fd < 0) { if (errno == ENOENT) { REFTABLE_CALLOC_ARRAY(*namesp, 1); + if (!*namesp) + return REFTABLE_OUT_OF_MEMORY_ERROR; return 0; } @@ -133,18 +170,18 @@ int read_lines(const char *filename, char ***namesp) return err; } -void reftable_stack_init_ref_iterator(struct reftable_stack *st, +int reftable_stack_init_ref_iterator(struct reftable_stack *st, struct reftable_iterator *it) { - merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_REF); + return merged_table_init_iter(reftable_stack_merged_table(st), + it, BLOCK_TYPE_REF); } -void reftable_stack_init_log_iterator(struct reftable_stack *st, - struct reftable_iterator *it) +int reftable_stack_init_log_iterator(struct reftable_stack *st, + struct reftable_iterator *it) { - merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_LOG); + return merged_table_init_iter(reftable_stack_merged_table(st), + it, BLOCK_TYPE_LOG); } struct reftable_merged_table * @@ -168,6 +205,10 @@ void reftable_stack_destroy(struct reftable_stack *st) { char **names = NULL; int err = 0; + + if (!st) + return; + if (st->merged) { reftable_merged_table_free(st->merged); st->merged = NULL; @@ -175,28 +216,31 @@ void reftable_stack_destroy(struct reftable_stack *st) err = read_lines(st->list_file, &names); if (err < 0) { - FREE_AND_NULL(names); + REFTABLE_FREE_AND_NULL(names); } if (st->readers) { int i = 0; - struct strbuf filename = STRBUF_INIT; + struct reftable_buf filename = REFTABLE_BUF_INIT; for (i = 0; i < st->readers_len; i++) { const char *name = reader_name(st->readers[i]); - strbuf_reset(&filename); + int try_unlinking = 1; + + reftable_buf_reset(&filename); if (names && !has_name(names, name)) { - stack_filename(&filename, st, name); + if (stack_filename(&filename, st, name) < 0) + try_unlinking = 0; } - reftable_reader_free(st->readers[i]); + reftable_reader_decref(st->readers[i]); - if (filename.len) { + if (try_unlinking && filename.len) { /* On Windows, can only unlink after closing. */ unlink(filename.buf); } } - strbuf_release(&filename); + reftable_buf_release(&filename); st->readers_len = 0; - FREE_AND_NULL(st->readers); + REFTABLE_FREE_AND_NULL(st->readers); } if (st->list_fd >= 0) { @@ -204,20 +248,20 @@ void reftable_stack_destroy(struct reftable_stack *st) st->list_fd = -1; } - FREE_AND_NULL(st->list_file); - FREE_AND_NULL(st->reftable_dir); + REFTABLE_FREE_AND_NULL(st->list_file); + REFTABLE_FREE_AND_NULL(st->reftable_dir); reftable_free(st); free_names(names); } static struct reftable_reader **stack_copy_readers(struct reftable_stack *st, - int cur_len) + size_t cur_len) { struct reftable_reader **cur = reftable_calloc(cur_len, sizeof(*cur)); - int i = 0; - for (i = 0; i < cur_len; i++) { + if (!cur) + return NULL; + for (size_t i = 0; i < cur_len; i++) cur[i] = st->readers[i]; - } return cur; } @@ -225,19 +269,31 @@ static int reftable_stack_reload_once(struct reftable_stack *st, const char **names, int reuse_open) { - size_t cur_len = !st->merged ? 0 : st->merged->stack_len; - struct reftable_reader **cur = stack_copy_readers(st, cur_len); - size_t names_len = names_length(names); - struct reftable_reader **new_readers = - reftable_calloc(names_len, sizeof(*new_readers)); - struct reftable_table *new_tables = - reftable_calloc(names_len, sizeof(*new_tables)); + size_t cur_len = !st->merged ? 0 : st->merged->readers_len; + struct reftable_reader **cur; + struct reftable_reader **reused = NULL; + struct reftable_reader **new_readers; + size_t reused_len = 0, reused_alloc = 0, names_len; size_t new_readers_len = 0; struct reftable_merged_table *new_merged = NULL; - struct strbuf table_path = STRBUF_INIT; + struct reftable_buf table_path = REFTABLE_BUF_INIT; int err = 0; size_t i; + cur = stack_copy_readers(st, cur_len); + if (!cur) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + + names_len = names_length(names); + + new_readers = reftable_calloc(names_len, sizeof(*new_readers)); + if (!new_readers) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + while (*names) { struct reftable_reader *rd = NULL; const char *name = *names++; @@ -248,70 +304,100 @@ static int reftable_stack_reload_once(struct reftable_stack *st, if (cur[i] && 0 == strcmp(cur[i]->name, name)) { rd = cur[i]; cur[i] = NULL; + + /* + * When reloading the stack fails, we end up + * releasing all new readers. This also + * includes the reused readers, even though + * they are still in used by the old stack. We + * thus need to keep them alive here, which we + * do by bumping their refcount. + */ + REFTABLE_ALLOC_GROW(reused, reused_len + 1, reused_alloc); + if (!reused) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + reused[reused_len++] = rd; + reftable_reader_incref(rd); break; } } if (!rd) { struct reftable_block_source src = { NULL }; - stack_filename(&table_path, st, name); + + err = stack_filename(&table_path, st, name); + if (err < 0) + goto done; err = reftable_block_source_from_file(&src, table_path.buf); if (err < 0) goto done; - err = reftable_new_reader(&rd, &src, name); + err = reftable_reader_new(&rd, &src, name); if (err < 0) goto done; } new_readers[new_readers_len] = rd; - reftable_table_from_reader(&new_tables[new_readers_len], rd); new_readers_len++; } /* success! */ - err = reftable_new_merged_table(&new_merged, new_tables, + err = reftable_merged_table_new(&new_merged, new_readers, new_readers_len, st->opts.hash_id); if (err < 0) goto done; - new_tables = NULL; - st->readers_len = new_readers_len; - if (st->merged) - reftable_merged_table_free(st->merged); - if (st->readers) { - reftable_free(st->readers); - } - st->readers = new_readers; - new_readers = NULL; - new_readers_len = 0; - - new_merged->suppress_deletions = 1; - st->merged = new_merged; + /* + * Close the old, non-reused readers and proactively try to unlink + * them. This is done for systems like Windows, where the underlying + * file of such an open reader wouldn't have been possible to be + * unlinked by the compacting process. + */ for (i = 0; i < cur_len; i++) { if (cur[i]) { const char *name = reader_name(cur[i]); - stack_filename(&table_path, st, name); - reader_close(cur[i]); - reftable_reader_free(cur[i]); + err = stack_filename(&table_path, st, name); + if (err < 0) + goto done; - /* On Windows, can only unlink after closing. */ + reftable_reader_decref(cur[i]); unlink(table_path.buf); } } + /* Update the stack to point to the new tables. */ + if (st->merged) + reftable_merged_table_free(st->merged); + new_merged->suppress_deletions = 1; + st->merged = new_merged; + + if (st->readers) + reftable_free(st->readers); + st->readers = new_readers; + st->readers_len = new_readers_len; + new_readers = NULL; + new_readers_len = 0; + + /* + * Decrement the refcount of reused readers again. This only needs to + * happen on the successful case, because on the unsuccessful one we + * decrement their refcount via `new_readers`. + */ + for (i = 0; i < reused_len; i++) + reftable_reader_decref(reused[i]); + done: - for (i = 0; i < new_readers_len; i++) { - reader_close(new_readers[i]); - reftable_reader_free(new_readers[i]); - } + for (i = 0; i < new_readers_len; i++) + reftable_reader_decref(new_readers[i]); reftable_free(new_readers); - reftable_free(new_tables); + reftable_free(reused); reftable_free(cur); - strbuf_release(&table_path); + reftable_buf_release(&table_path); return err; } @@ -364,6 +450,10 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, } REFTABLE_CALLOC_ARRAY(names, 1); + if (!names) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } } else { err = fd_read_lines(fd, &names); if (err < 0) @@ -458,6 +548,10 @@ out: close(fd); free_names(names); free_names(names_after); + + if (st->opts.on_reload) + st->opts.on_reload(st->opts.on_reload_payload); + return err; } @@ -520,7 +614,7 @@ static int stack_uptodate(struct reftable_stack *st) } } - if (names[st->merged->stack_len]) { + if (names[st->merged->readers_len]) { err = 1; goto done; } @@ -556,18 +650,18 @@ int reftable_stack_add(struct reftable_stack *st, return 0; } -static void format_name(struct strbuf *dest, uint64_t min, uint64_t max) +static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) { char buf[100]; uint32_t rnd = (uint32_t)git_rand(); snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", min, max, rnd); - strbuf_reset(dest); - strbuf_addstr(dest, buf); + reftable_buf_reset(dest); + return reftable_buf_addstr(dest, buf); } struct reftable_addition { - struct tempfile *lock_file; + struct reftable_flock tables_list_lock; struct reftable_stack *stack; char **new_tables; @@ -578,16 +672,17 @@ struct reftable_addition { #define REFTABLE_ADDITION_INIT {0} static int reftable_stack_init_addition(struct reftable_addition *add, - struct reftable_stack *st) + struct reftable_stack *st, + unsigned int flags) { - struct strbuf lock_file_name = STRBUF_INIT; - int err = 0; - add->stack = st; + struct reftable_buf lock_file_name = REFTABLE_BUF_INIT; + int err; - strbuf_addf(&lock_file_name, "%s.lock", st->list_file); + add->stack = st; - add->lock_file = create_tempfile(lock_file_name.buf); - if (!add->lock_file) { + err = flock_acquire(&add->tables_list_lock, st->list_file, + st->opts.lock_timeout_ms); + if (err < 0) { if (errno == EEXIST) { err = REFTABLE_LOCK_ERROR; } else { @@ -596,7 +691,8 @@ static int reftable_stack_init_addition(struct reftable_addition *add, goto done; } if (st->opts.default_permissions) { - if (chmod(add->lock_file->filename.buf, st->opts.default_permissions) < 0) { + if (chmod(add->tables_list_lock.path, + st->opts.default_permissions) < 0) { err = REFTABLE_IO_ERROR; goto done; } @@ -605,6 +701,11 @@ static int reftable_stack_init_addition(struct reftable_addition *add, err = stack_uptodate(st); if (err < 0) goto done; + if (err > 0 && flags & REFTABLE_STACK_NEW_ADDITION_RELOAD) { + err = reftable_stack_reload_maybe_reuse(add->stack, 1); + if (err) + goto done; + } if (err > 0) { err = REFTABLE_OUTDATED_ERROR; goto done; @@ -612,21 +713,20 @@ static int reftable_stack_init_addition(struct reftable_addition *add, add->next_update_index = reftable_stack_next_update_index(st); done: - if (err) { + if (err) reftable_addition_close(add); - } - strbuf_release(&lock_file_name); + reftable_buf_release(&lock_file_name); return err; } static void reftable_addition_close(struct reftable_addition *add) { - struct strbuf nm = STRBUF_INIT; + struct reftable_buf nm = REFTABLE_BUF_INIT; size_t i; for (i = 0; i < add->new_tables_len; i++) { - stack_filename(&nm, add->stack, add->new_tables[i]); - unlink(nm.buf); + if (!stack_filename(&nm, add->stack, add->new_tables[i])) + unlink(nm.buf); reftable_free(add->new_tables[i]); add->new_tables[i] = NULL; } @@ -635,8 +735,8 @@ static void reftable_addition_close(struct reftable_addition *add) add->new_tables_len = 0; add->new_tables_cap = 0; - delete_tempfile(&add->lock_file); - strbuf_release(&nm); + flock_release(&add->tables_list_lock); + reftable_buf_release(&nm); } void reftable_addition_destroy(struct reftable_addition *add) @@ -650,34 +750,38 @@ void reftable_addition_destroy(struct reftable_addition *add) int reftable_addition_commit(struct reftable_addition *add) { - struct strbuf table_list = STRBUF_INIT; - int lock_file_fd = get_tempfile_fd(add->lock_file); + struct reftable_buf table_list = REFTABLE_BUF_INIT; int err = 0; size_t i; if (add->new_tables_len == 0) goto done; - for (i = 0; i < add->stack->merged->stack_len; i++) { - strbuf_addstr(&table_list, add->stack->readers[i]->name); - strbuf_addstr(&table_list, "\n"); + for (i = 0; i < add->stack->merged->readers_len; i++) { + if ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 || + (err = reftable_buf_addstr(&table_list, "\n")) < 0) + goto done; } for (i = 0; i < add->new_tables_len; i++) { - strbuf_addstr(&table_list, add->new_tables[i]); - strbuf_addstr(&table_list, "\n"); + if ((err = reftable_buf_addstr(&table_list, add->new_tables[i])) < 0 || + (err = reftable_buf_addstr(&table_list, "\n")) < 0) + goto done; } - err = write_in_full(lock_file_fd, table_list.buf, table_list.len); - strbuf_release(&table_list); + err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len); + reftable_buf_release(&table_list); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; } - fsync_component_or_die(FSYNC_COMPONENT_REFERENCE, lock_file_fd, - get_tempfile_path(add->lock_file)); + err = stack_fsync(&add->stack->opts, add->tables_list_lock.fd); + if (err < 0) { + err = REFTABLE_IO_ERROR; + goto done; + } - err = rename_tempfile(&add->lock_file, add->stack->list_file); + err = flock_commit(&add->tables_list_lock); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; @@ -715,13 +819,18 @@ done: } int reftable_stack_new_addition(struct reftable_addition **dest, - struct reftable_stack *st) + struct reftable_stack *st, + unsigned int flags) { int err = 0; struct reftable_addition empty = REFTABLE_ADDITION_INIT; + REFTABLE_CALLOC_ARRAY(*dest, 1); + if (!*dest) + return REFTABLE_OUT_OF_MEMORY_ERROR; + **dest = empty; - err = reftable_stack_init_addition(*dest, st); + err = reftable_stack_init_addition(*dest, st, flags); if (err) { reftable_free(*dest); *dest = NULL; @@ -735,7 +844,7 @@ static int stack_try_add(struct reftable_stack *st, void *arg) { struct reftable_addition add = REFTABLE_ADDITION_INIT; - int err = reftable_stack_init_addition(&add, st); + int err = reftable_stack_init_addition(&add, st, 0); if (err < 0) goto done; @@ -754,36 +863,47 @@ int reftable_addition_add(struct reftable_addition *add, void *arg), void *arg) { - struct strbuf temp_tab_file_name = STRBUF_INIT; - struct strbuf tab_file_name = STRBUF_INIT; - struct strbuf next_name = STRBUF_INIT; + struct reftable_buf temp_tab_file_name = REFTABLE_BUF_INIT; + struct reftable_buf tab_file_name = REFTABLE_BUF_INIT; + struct reftable_buf next_name = REFTABLE_BUF_INIT; struct reftable_writer *wr = NULL; - struct tempfile *tab_file = NULL; + struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; + struct fd_writer writer = { + .opts = &add->stack->opts, + }; int err = 0; - int tab_fd; - strbuf_reset(&next_name); - format_name(&next_name, add->next_update_index, add->next_update_index); + reftable_buf_reset(&next_name); - stack_filename(&temp_tab_file_name, add->stack, next_name.buf); - strbuf_addstr(&temp_tab_file_name, ".temp.XXXXXX"); + err = format_name(&next_name, add->next_update_index, add->next_update_index); + if (err < 0) + goto done; - tab_file = mks_tempfile(temp_tab_file_name.buf); - if (!tab_file) { - err = REFTABLE_IO_ERROR; + err = stack_filename(&temp_tab_file_name, add->stack, next_name.buf); + if (err < 0) + goto done; + + err = reftable_buf_addstr(&temp_tab_file_name, ".temp.XXXXXX"); + if (err < 0) + goto done; + + err = tmpfile_from_pattern(&tab_file, temp_tab_file_name.buf); + if (err < 0) goto done; - } if (add->stack->opts.default_permissions) { - if (chmod(get_tempfile_path(tab_file), + if (chmod(tab_file.path, add->stack->opts.default_permissions)) { err = REFTABLE_IO_ERROR; goto done; } } - tab_fd = get_tempfile_fd(tab_file); - wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd, - &add->stack->opts); + writer.fd = tab_file.fd; + err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, + &writer, &add->stack->opts); + if (err < 0) + goto done; + err = write_table(wr, arg); if (err < 0) goto done; @@ -796,46 +916,55 @@ int reftable_addition_add(struct reftable_addition *add, if (err < 0) goto done; - err = close_tempfile_gently(tab_file); - if (err < 0) { - err = REFTABLE_IO_ERROR; + err = tmpfile_close(&tab_file); + if (err < 0) goto done; - } if (wr->min_update_index < add->next_update_index) { err = REFTABLE_API_ERROR; goto done; } - format_name(&next_name, wr->min_update_index, wr->max_update_index); - strbuf_addstr(&next_name, ".ref"); - stack_filename(&tab_file_name, add->stack, next_name.buf); + err = format_name(&next_name, wr->min_update_index, wr->max_update_index); + if (err < 0) + goto done; + + err = reftable_buf_addstr(&next_name, ".ref"); + if (err < 0) + goto done; + + err = stack_filename(&tab_file_name, add->stack, next_name.buf); + if (err < 0) + goto done; /* On windows, this relies on rand() picking a unique destination name. Maybe we should do retry loop as well? */ - err = rename_tempfile(&tab_file, tab_file_name.buf); - if (err < 0) { - err = REFTABLE_IO_ERROR; + err = tmpfile_rename(&tab_file, tab_file_name.buf); + if (err < 0) goto done; - } REFTABLE_ALLOC_GROW(add->new_tables, add->new_tables_len + 1, add->new_tables_cap); - add->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL); + if (!add->new_tables) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + add->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name); + done: - delete_tempfile(&tab_file); - strbuf_release(&temp_tab_file_name); - strbuf_release(&tab_file_name); - strbuf_release(&next_name); + tmpfile_delete(&tab_file); + reftable_buf_release(&temp_tab_file_name); + reftable_buf_release(&tab_file_name); + reftable_buf_release(&next_name); reftable_writer_free(wr); return err; } uint64_t reftable_stack_next_update_index(struct reftable_stack *st) { - int sz = st->merged->stack_len; + int sz = st->merged->readers_len; if (sz > 0) return reftable_reader_max_update_index(st->readers[sz - 1]) + 1; @@ -845,35 +974,46 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st) static int stack_compact_locked(struct reftable_stack *st, size_t first, size_t last, struct reftable_log_expiry_config *config, - struct tempfile **tab_file_out) + struct reftable_tmpfile *tab_file_out) { - struct strbuf next_name = STRBUF_INIT; - struct strbuf tab_file_path = STRBUF_INIT; + struct reftable_buf next_name = REFTABLE_BUF_INIT; + struct reftable_buf tab_file_path = REFTABLE_BUF_INIT; struct reftable_writer *wr = NULL; - struct tempfile *tab_file; - int tab_fd, err = 0; + struct fd_writer writer= { + .opts = &st->opts, + }; + struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; + int err = 0; + + err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]), + reftable_reader_max_update_index(st->readers[last])); + if (err < 0) + goto done; - format_name(&next_name, - reftable_reader_min_update_index(st->readers[first]), - reftable_reader_max_update_index(st->readers[last])); - stack_filename(&tab_file_path, st, next_name.buf); - strbuf_addstr(&tab_file_path, ".temp.XXXXXX"); + err = stack_filename(&tab_file_path, st, next_name.buf); + if (err < 0) + goto done; - tab_file = mks_tempfile(tab_file_path.buf); - if (!tab_file) { - err = REFTABLE_IO_ERROR; + err = reftable_buf_addstr(&tab_file_path, ".temp.XXXXXX"); + if (err < 0) + goto done; + + err = tmpfile_from_pattern(&tab_file, tab_file_path.buf); + if (err < 0) goto done; - } - tab_fd = get_tempfile_fd(tab_file); if (st->opts.default_permissions && - chmod(get_tempfile_path(tab_file), st->opts.default_permissions) < 0) { + chmod(tab_file.path, st->opts.default_permissions) < 0) { err = REFTABLE_IO_ERROR; goto done; } - wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, - &tab_fd, &st->opts); + writer.fd = tab_file.fd; + err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, + &writer, &st->opts); + if (err < 0) + goto done; + err = stack_write_compact(st, wr, first, last, config); if (err < 0) goto done; @@ -882,18 +1022,18 @@ static int stack_compact_locked(struct reftable_stack *st, if (err < 0) goto done; - err = close_tempfile_gently(tab_file); + err = tmpfile_close(&tab_file); if (err < 0) goto done; *tab_file_out = tab_file; - tab_file = NULL; + tab_file = REFTABLE_TMPFILE_INIT; done: - delete_tempfile(&tab_file); + tmpfile_delete(&tab_file); reftable_writer_free(wr); - strbuf_release(&next_name); - strbuf_release(&tab_file_path); + reftable_buf_release(&next_name); + reftable_buf_release(&tab_file_path); return err; } @@ -902,32 +1042,28 @@ static int stack_write_compact(struct reftable_stack *st, size_t first, size_t last, struct reftable_log_expiry_config *config) { - size_t subtabs_len = last - first + 1; - struct reftable_table *subtabs = reftable_calloc( - last - first + 1, sizeof(*subtabs)); struct reftable_merged_table *mt = NULL; struct reftable_iterator it = { NULL }; struct reftable_ref_record ref = { NULL }; struct reftable_log_record log = { NULL }; + size_t subtabs_len = last - first + 1; uint64_t entries = 0; int err = 0; - for (size_t i = first, j = 0; i <= last; i++) { - struct reftable_reader *t = st->readers[i]; - reftable_table_from_reader(&subtabs[j++], t); - st->stats.bytes += t->size; - } + for (size_t i = first; i <= last; i++) + st->stats.bytes += st->readers[i]->size; reftable_writer_set_limits(wr, st->readers[first]->min_update_index, st->readers[last]->max_update_index); - err = reftable_new_merged_table(&mt, subtabs, subtabs_len, + err = reftable_merged_table_new(&mt, st->readers + first, subtabs_len, st->opts.hash_id); - if (err < 0) { - reftable_free(subtabs); + if (err < 0) + goto done; + + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + if (err < 0) goto done; - } - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); err = reftable_iterator_seek_ref(&it, ""); if (err < 0) goto done; @@ -952,7 +1088,10 @@ static int stack_write_compact(struct reftable_stack *st, } reftable_iterator_destroy(&it); - merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + if (err < 0) + goto done; + err = reftable_iterator_seek_log(&it, ""); if (err < 0) goto done; @@ -995,6 +1134,15 @@ done: return err; } +enum stack_compact_range_flags { + /* + * Perform a best-effort compaction. That is, even if we cannot lock + * all tables in the specified range, we will try to compact the + * remaining slice. + */ + STACK_COMPACT_RANGE_BEST_EFFORT = (1 << 0), +}; + /* * Compact all tables in the range `[first, last)` into a single new table. * @@ -1006,17 +1154,20 @@ done: */ static int stack_compact_range(struct reftable_stack *st, size_t first, size_t last, - struct reftable_log_expiry_config *expiry) + struct reftable_log_expiry_config *expiry, + unsigned int flags) { - struct strbuf tables_list_buf = STRBUF_INIT; - struct strbuf new_table_name = STRBUF_INIT; - struct strbuf new_table_path = STRBUF_INIT; - struct strbuf table_name = STRBUF_INIT; - struct lock_file tables_list_lock = LOCK_INIT; - struct lock_file *table_locks = NULL; - struct tempfile *new_table = NULL; + struct reftable_buf tables_list_buf = REFTABLE_BUF_INIT; + struct reftable_buf new_table_name = REFTABLE_BUF_INIT; + struct reftable_buf new_table_path = REFTABLE_BUF_INIT; + struct reftable_buf table_name = REFTABLE_BUF_INIT; + struct reftable_flock tables_list_lock = REFTABLE_FLOCK_INIT; + struct reftable_flock *table_locks = NULL; + struct reftable_tmpfile new_table = REFTABLE_TMPFILE_INIT; int is_empty_table = 0, err = 0; - size_t i; + size_t first_to_replace, last_to_replace; + size_t i, nlocks = 0; + char **names = NULL; if (first > last || (!expiry && first == last)) { err = 0; @@ -1029,8 +1180,7 @@ static int stack_compact_range(struct reftable_stack *st, * Hold the lock so that we can read "tables.list" and lock all tables * which are part of the user-specified range. */ - err = hold_lock_file_for_update(&tables_list_lock, st->list_file, - LOCK_NO_DEREF); + err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); if (err < 0) { if (errno == EEXIST) err = REFTABLE_LOCK_ERROR; @@ -1046,19 +1196,55 @@ static int stack_compact_range(struct reftable_stack *st, /* * Lock all tables in the user-provided range. This is the slice of our * stack which we'll compact. + * + * Note that we lock tables in reverse order from last to first. The + * intent behind this is to allow a newer process to perform best + * effort compaction of tables that it has added in the case where an + * older process is still busy compacting tables which are preexisting + * from the point of view of the newer process. */ - REFTABLE_CALLOC_ARRAY(table_locks, last - first + 1); - for (i = first; i <= last; i++) { - stack_filename(&table_name, st, reader_name(st->readers[i])); + REFTABLE_ALLOC_ARRAY(table_locks, last - first + 1); + if (!table_locks) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + for (i = 0; i < last - first + 1; i++) + table_locks[i] = REFTABLE_FLOCK_INIT; + + for (i = last + 1; i > first; i--) { + err = stack_filename(&table_name, st, reader_name(st->readers[i - 1])); + if (err < 0) + goto done; - err = hold_lock_file_for_update(&table_locks[i - first], - table_name.buf, LOCK_NO_DEREF); + err = flock_acquire(&table_locks[nlocks], table_name.buf, 0); if (err < 0) { - if (errno == EEXIST) + /* + * When the table is locked already we may do a + * best-effort compaction and compact only the tables + * that we have managed to lock so far. This of course + * requires that we have been able to lock at least two + * tables, otherwise there would be nothing to compact. + * In that case, we return a lock error to our caller. + */ + if (errno == EEXIST && last - (i - 1) >= 2 && + flags & STACK_COMPACT_RANGE_BEST_EFFORT) { + err = 0; + /* + * The subtraction is to offset the index, the + * addition is to only compact up to the table + * of the preceding iteration. They obviously + * cancel each other out, but that may be + * non-obvious when it was omitted. + */ + first = (i - 1) + 1; + break; + } else if (errno == EEXIST) { err = REFTABLE_LOCK_ERROR; - else + goto done; + } else { err = REFTABLE_IO_ERROR; - goto done; + goto done; + } } /* @@ -1066,7 +1252,7 @@ static int stack_compact_range(struct reftable_stack *st, * run into file descriptor exhaustion when we compress a lot * of tables. */ - err = close_lock_file_gently(&table_locks[i - first]); + err = flock_close(&table_locks[nlocks++]); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; @@ -1078,7 +1264,7 @@ static int stack_compact_range(struct reftable_stack *st, * "tables.list" lock while compacting the locked tables. This allows * concurrent updates to the stack to proceed. */ - err = rollback_lock_file(&tables_list_lock); + err = flock_release(&tables_list_lock); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; @@ -1101,8 +1287,7 @@ static int stack_compact_range(struct reftable_stack *st, * "tables.list". We'll then replace the compacted range of tables with * the new table. */ - err = hold_lock_file_for_update(&tables_list_lock, st->list_file, - LOCK_NO_DEREF); + err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); if (err < 0) { if (errno == EEXIST) err = REFTABLE_LOCK_ERROR; @@ -1112,7 +1297,7 @@ static int stack_compact_range(struct reftable_stack *st, } if (st->opts.default_permissions) { - if (chmod(get_lock_file_path(&tables_list_lock), + if (chmod(tables_list_lock.path, st->opts.default_permissions) < 0) { err = REFTABLE_IO_ERROR; goto done; @@ -1120,20 +1305,130 @@ static int stack_compact_range(struct reftable_stack *st, } /* + * As we have unlocked the stack while compacting our slice of tables + * it may have happened that a concurrently running process has updated + * the stack while we were compacting. In that case, we need to check + * whether the tables that we have just compacted still exist in the + * stack in the exact same order as we have compacted them. + * + * If they do exist, then it is fine to continue and replace those + * tables with our compacted version. If they don't, then we need to + * abort. + */ + err = stack_uptodate(st); + if (err < 0) + goto done; + if (err > 0) { + ssize_t new_offset = -1; + int fd; + + fd = open(st->list_file, O_RDONLY); + if (fd < 0) { + err = REFTABLE_IO_ERROR; + goto done; + } + + err = fd_read_lines(fd, &names); + close(fd); + if (err < 0) + goto done; + + /* + * Search for the offset of the first table that we have + * compacted in the updated "tables.list" file. + */ + for (size_t i = 0; names[i]; i++) { + if (strcmp(names[i], st->readers[first]->name)) + continue; + + /* + * We have found the first entry. Verify that all the + * subsequent tables we have compacted still exist in + * the modified stack in the exact same order as we + * have compacted them. + */ + for (size_t j = 1; j < last - first + 1; j++) { + const char *old = first + j < st->merged->readers_len ? + st->readers[first + j]->name : NULL; + const char *new = names[i + j]; + + /* + * If some entries are missing or in case the tables + * have changed then we need to bail out. Again, this + * shouldn't ever happen because we have locked the + * tables we are compacting. + */ + if (!old || !new || strcmp(old, new)) { + err = REFTABLE_OUTDATED_ERROR; + goto done; + } + } + + new_offset = i; + break; + } + + /* + * In case we didn't find our compacted tables in the stack we + * need to bail out. In theory, this should have never happened + * because we locked the tables we are compacting. + */ + if (new_offset < 0) { + err = REFTABLE_OUTDATED_ERROR; + goto done; + } + + /* + * We have found the new range that we want to replace, so + * let's update the range of tables that we want to replace. + */ + first_to_replace = new_offset; + last_to_replace = last + (new_offset - first); + } else { + /* + * `fd_read_lines()` uses a `NULL` sentinel to indicate that + * the array is at its end. As we use `free_names()` to free + * the array, we need to include this sentinel value here and + * thus have to allocate `readers_len + 1` many entries. + */ + REFTABLE_CALLOC_ARRAY(names, st->merged->readers_len + 1); + if (!names) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + + for (size_t i = 0; i < st->merged->readers_len; i++) { + names[i] = reftable_strdup(st->readers[i]->name); + if (!names[i]) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } + } + first_to_replace = first; + last_to_replace = last; + } + + /* * If the resulting compacted table is not empty, then we need to move * it into place now. */ if (!is_empty_table) { - format_name(&new_table_name, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); - strbuf_addstr(&new_table_name, ".ref"); - stack_filename(&new_table_path, st, new_table_name.buf); + err = format_name(&new_table_name, st->readers[first]->min_update_index, + st->readers[last]->max_update_index); + if (err < 0) + goto done; - err = rename_tempfile(&new_table, new_table_path.buf); - if (err < 0) { - err = REFTABLE_IO_ERROR; + err = reftable_buf_addstr(&new_table_name, ".ref"); + if (err < 0) + goto done; + + err = stack_filename(&new_table_path, st, new_table_name.buf); + if (err < 0) + goto done; + + err = tmpfile_rename(&new_table, new_table_path.buf); + if (err < 0) goto done; - } } /* @@ -1141,14 +1436,23 @@ static int stack_compact_range(struct reftable_stack *st, * have just written. In case the compacted table became empty we * simply skip writing it. */ - for (i = 0; i < first; i++) - strbuf_addf(&tables_list_buf, "%s\n", st->readers[i]->name); - if (!is_empty_table) - strbuf_addf(&tables_list_buf, "%s\n", new_table_name.buf); - for (i = last + 1; i < st->merged->stack_len; i++) - strbuf_addf(&tables_list_buf, "%s\n", st->readers[i]->name); - - err = write_in_full(get_lock_file_fd(&tables_list_lock), + for (i = 0; i < first_to_replace; i++) { + if ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 || + (err = reftable_buf_addstr(&tables_list_buf, "\n")) < 0) + goto done; + } + if (!is_empty_table) { + if ((err = reftable_buf_addstr(&tables_list_buf, new_table_name.buf)) < 0 || + (err = reftable_buf_addstr(&tables_list_buf, "\n")) < 0) + goto done; + } + for (i = last_to_replace + 1; names[i]; i++) { + if ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 || + (err = reftable_buf_addstr(&tables_list_buf, "\n")) < 0) + goto done; + } + + err = write_in_full(tables_list_lock.fd, tables_list_buf.buf, tables_list_buf.len); if (err < 0) { err = REFTABLE_IO_ERROR; @@ -1156,14 +1460,14 @@ static int stack_compact_range(struct reftable_stack *st, goto done; } - err = fsync_component(FSYNC_COMPONENT_REFERENCE, get_lock_file_fd(&tables_list_lock)); + err = stack_fsync(&st->opts, tables_list_lock.fd); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); goto done; } - err = commit_lock_file(&tables_list_lock); + err = flock_commit(&tables_list_lock); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); @@ -1183,43 +1487,42 @@ static int stack_compact_range(struct reftable_stack *st, * Delete the old tables. They may still be in use by concurrent * readers, so it is expected that unlinking tables may fail. */ - for (i = first; i <= last; i++) { - struct lock_file *table_lock = &table_locks[i - first]; - char *table_path = get_locked_file_path(table_lock); - unlink(table_path); - free(table_path); + for (i = 0; i < nlocks; i++) { + struct reftable_flock *table_lock = &table_locks[i]; + + reftable_buf_reset(&table_name); + err = reftable_buf_add(&table_name, table_lock->path, + strlen(table_lock->path) - strlen(".lock")); + if (err) + continue; + + unlink(table_name.buf); } done: - rollback_lock_file(&tables_list_lock); - for (i = first; table_locks && i <= last; i++) - rollback_lock_file(&table_locks[i - first]); + flock_release(&tables_list_lock); + for (i = 0; table_locks && i < nlocks; i++) + flock_release(&table_locks[i]); reftable_free(table_locks); - delete_tempfile(&new_table); - strbuf_release(&new_table_name); - strbuf_release(&new_table_path); + tmpfile_delete(&new_table); + reftable_buf_release(&new_table_name); + reftable_buf_release(&new_table_path); + reftable_buf_release(&tables_list_buf); + reftable_buf_release(&table_name); + free_names(names); + + if (err == REFTABLE_LOCK_ERROR) + st->stats.failures++; - strbuf_release(&tables_list_buf); - strbuf_release(&table_name); return err; } int reftable_stack_compact_all(struct reftable_stack *st, struct reftable_log_expiry_config *config) { - return stack_compact_range(st, 0, st->merged->stack_len ? - st->merged->stack_len - 1 : 0, config); -} - -static int stack_compact_range_stats(struct reftable_stack *st, - size_t first, size_t last, - struct reftable_log_expiry_config *config) -{ - int err = stack_compact_range(st, first, last, config); - if (err == REFTABLE_LOCK_ERROR) - st->stats.failures++; - return err; + size_t last = st->merged->readers_len ? st->merged->readers_len - 1 : 0; + return stack_compact_range(st, 0, last, config, 0); } static int segment_size(struct segment *s) @@ -1305,27 +1608,36 @@ struct segment suggest_compaction_segment(uint64_t *sizes, size_t n, static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) { - uint64_t *sizes = - reftable_calloc(st->merged->stack_len, sizeof(*sizes)); - int version = (st->opts.hash_id == GIT_SHA1_FORMAT_ID) ? 1 : 2; + int version = (st->opts.hash_id == REFTABLE_HASH_SHA1) ? 1 : 2; int overhead = header_size(version) - 1; - int i = 0; - for (i = 0; i < st->merged->stack_len; i++) { + uint64_t *sizes; + + REFTABLE_CALLOC_ARRAY(sizes, st->merged->readers_len); + if (!sizes) + return NULL; + + for (size_t i = 0; i < st->merged->readers_len; i++) sizes[i] = st->readers[i]->size - overhead; - } + return sizes; } int reftable_stack_auto_compact(struct reftable_stack *st) { - uint64_t *sizes = stack_table_sizes_for_compaction(st); - struct segment seg = - suggest_compaction_segment(sizes, st->merged->stack_len, - st->opts.auto_compaction_factor); + struct segment seg; + uint64_t *sizes; + + sizes = stack_table_sizes_for_compaction(st); + if (!sizes) + return REFTABLE_OUT_OF_MEMORY_ERROR; + + seg = suggest_compaction_segment(sizes, st->merged->readers_len, + st->opts.auto_compaction_factor); reftable_free(sizes); + if (segment_size(&seg) > 0) - return stack_compact_range_stats(st, seg.start, seg.end - 1, - NULL); + return stack_compact_range(st, seg.start, seg.end - 1, + NULL, STACK_COMPACT_RANGE_BEST_EFFORT); return 0; } @@ -1339,9 +1651,31 @@ reftable_stack_compaction_stats(struct reftable_stack *st) int reftable_stack_read_ref(struct reftable_stack *st, const char *refname, struct reftable_ref_record *ref) { - struct reftable_table tab = { NULL }; - reftable_table_from_merged_table(&tab, reftable_stack_merged_table(st)); - return reftable_table_read_ref(&tab, refname, ref); + struct reftable_iterator it = { 0 }; + int ret; + + ret = reftable_merged_table_init_ref_iterator(st->merged, &it); + if (ret) + goto out; + + ret = reftable_iterator_seek_ref(&it, refname); + if (ret) + goto out; + + ret = reftable_iterator_next_ref(&it, ref); + if (ret) + goto out; + + if (strcmp(ref->refname, refname) || + reftable_ref_record_is_deletion(ref)) { + reftable_ref_record_release(ref); + ret = 1; + goto out; + } + +out: + reftable_iterator_destroy(&it); + return ret; } int reftable_stack_read_log(struct reftable_stack *st, const char *refname, @@ -1350,7 +1684,10 @@ int reftable_stack_read_log(struct reftable_stack *st, const char *refname, struct reftable_iterator it = {0}; int err; - reftable_stack_init_log_iterator(st, &it); + err = reftable_stack_init_log_iterator(st, &it); + if (err) + goto done; + err = reftable_iterator_seek_log(&it, refname); if (err) goto done; @@ -1386,25 +1723,28 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max, uint64_t update_idx = 0; struct reftable_block_source src = { NULL }; struct reftable_reader *rd = NULL; - struct strbuf table_path = STRBUF_INIT; - stack_filename(&table_path, st, name); + struct reftable_buf table_path = REFTABLE_BUF_INIT; + + err = stack_filename(&table_path, st, name); + if (err < 0) + goto done; err = reftable_block_source_from_file(&src, table_path.buf); if (err < 0) goto done; - err = reftable_new_reader(&rd, &src, name); + err = reftable_reader_new(&rd, &src, name); if (err < 0) goto done; update_idx = reftable_reader_max_update_index(rd); - reftable_reader_free(rd); + reftable_reader_decref(rd); if (update_idx <= max) { unlink(table_path.buf); } done: - strbuf_release(&table_path); + reftable_buf_release(&table_path); } static int reftable_stack_clean_locked(struct reftable_stack *st) @@ -1439,7 +1779,7 @@ static int reftable_stack_clean_locked(struct reftable_stack *st) int reftable_stack_clean(struct reftable_stack *st) { struct reftable_addition *add = NULL; - int err = reftable_stack_new_addition(&add, st); + int err = reftable_stack_new_addition(&add, st, 0); if (err < 0) { goto done; } @@ -1456,22 +1796,7 @@ done: return err; } -int reftable_stack_print_directory(const char *stackdir, uint32_t hash_id) +enum reftable_hash reftable_stack_hash_id(struct reftable_stack *st) { - struct reftable_stack *stack = NULL; - struct reftable_write_options opts = { .hash_id = hash_id }; - struct reftable_merged_table *merged = NULL; - struct reftable_table table = { NULL }; - - int err = reftable_new_stack(&stack, stackdir, &opts); - if (err < 0) - goto done; - - merged = reftable_stack_merged_table(stack); - reftable_table_from_merged_table(&table, merged); - err = reftable_table_print(&table); -done: - if (stack) - reftable_stack_destroy(stack); - return err; + return reftable_merged_table_hash_id(st->merged); } diff --git a/reftable/stack_test.c b/reftable/stack_test.c deleted file mode 100644 index e3c11e6a6e..0000000000 --- a/reftable/stack_test.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "stack.h" - -#include "system.h" - -#include "reftable-reader.h" -#include "merged.h" -#include "basics.h" -#include "record.h" -#include "test_framework.h" -#include "reftable-tests.h" -#include "reader.h" - -#include <sys/types.h> -#include <dirent.h> - -static void clear_dir(const char *dirname) -{ - struct strbuf path = STRBUF_INIT; - strbuf_addstr(&path, dirname); - remove_dir_recursively(&path, 0); - strbuf_release(&path); -} - -static int count_dir_entries(const char *dirname) -{ - DIR *dir = opendir(dirname); - int len = 0; - struct dirent *d; - if (!dir) - return 0; - - while ((d = readdir(dir))) { - /* - * Besides skipping over "." and "..", we also need to - * skip over other files that have a leading ".". This - * is due to behaviour of NFS, which will rename files - * to ".nfs*" to emulate delete-on-last-close. - * - * In any case this should be fine as the reftable - * library will never write files with leading dots - * anyway. - */ - if (starts_with(d->d_name, ".")) - continue; - len++; - } - closedir(dir); - return len; -} - -/* - * Work linenumber into the tempdir, so we can see which tests forget to - * cleanup. - */ -static char *get_tmp_template(int linenumber) -{ - const char *tmp = getenv("TMPDIR"); - static char template[1024]; - snprintf(template, sizeof(template) - 1, "%s/stack_test-%d.XXXXXX", - tmp ? tmp : "/tmp", linenumber); - return template; -} - -static char *get_tmp_dir(int linenumber) -{ - char *dir = get_tmp_template(linenumber); - EXPECT(mkdtemp(dir)); - return dir; -} - -static void test_read_file(void) -{ - char *fn = get_tmp_template(__LINE__); - int fd = mkstemp(fn); - char out[1024] = "line1\n\nline2\nline3"; - int n, err; - char **names = NULL; - const char *want[] = { "line1", "line2", "line3" }; - int i = 0; - - EXPECT(fd > 0); - n = write_in_full(fd, out, strlen(out)); - EXPECT(n == strlen(out)); - err = close(fd); - EXPECT(err >= 0); - - err = read_lines(fn, &names); - EXPECT_ERR(err); - - for (i = 0; names[i]; i++) { - EXPECT(0 == strcmp(want[i], names[i])); - } - free_names(names); - (void) remove(fn); -} - -static int write_test_ref(struct reftable_writer *wr, void *arg) -{ - struct reftable_ref_record *ref = arg; - reftable_writer_set_limits(wr, ref->update_index, ref->update_index); - return reftable_writer_add_ref(wr, ref); -} - -struct write_log_arg { - struct reftable_log_record *log; - uint64_t update_index; -}; - -static int write_test_log(struct reftable_writer *wr, void *arg) -{ - struct write_log_arg *wla = arg; - - reftable_writer_set_limits(wr, wla->update_index, wla->update_index); - return reftable_writer_add_log(wr, wla->log); -} - -static void test_reftable_stack_add_one(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct strbuf scratch = STRBUF_INIT; - int mask = umask(002); - struct reftable_write_options opts = { - .default_permissions = 0660, - }; - struct reftable_stack *st = NULL; - int err; - struct reftable_ref_record ref = { - .refname = (char *) "HEAD", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - struct reftable_ref_record dest = { NULL }; - struct stat stat_result = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st, &write_test_ref, &ref); - EXPECT_ERR(err); - - err = reftable_stack_read_ref(st, ref.refname, &dest); - EXPECT_ERR(err); - EXPECT(0 == strcmp("master", dest.value.symref)); - EXPECT(st->readers_len > 0); - - printf("testing print functionality:\n"); - err = reftable_stack_print_directory(dir, GIT_SHA1_FORMAT_ID); - EXPECT_ERR(err); - - err = reftable_stack_print_directory(dir, GIT_SHA256_FORMAT_ID); - EXPECT(err == REFTABLE_FORMAT_ERROR); - -#ifndef GIT_WINDOWS_NATIVE - strbuf_addstr(&scratch, dir); - strbuf_addstr(&scratch, "/tables.list"); - err = stat(scratch.buf, &stat_result); - EXPECT(!err); - EXPECT((stat_result.st_mode & 0777) == opts.default_permissions); - - strbuf_reset(&scratch); - strbuf_addstr(&scratch, dir); - strbuf_addstr(&scratch, "/"); - /* do not try at home; not an external API for reftable. */ - strbuf_addstr(&scratch, st->readers[0]->name); - err = stat(scratch.buf, &stat_result); - EXPECT(!err); - EXPECT((stat_result.st_mode & 0777) == opts.default_permissions); -#else - (void) stat_result; -#endif - - reftable_ref_record_release(&dest); - reftable_stack_destroy(st); - strbuf_release(&scratch); - clear_dir(dir); - umask(mask); -} - -static void test_reftable_stack_uptodate(void) -{ - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st1 = NULL; - struct reftable_stack *st2 = NULL; - char *dir = get_tmp_dir(__LINE__); - - int err; - struct reftable_ref_record ref1 = { - .refname = (char *) "HEAD", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - struct reftable_ref_record ref2 = { - .refname = (char *) "branch2", - .update_index = 2, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - - - /* simulate multi-process access to the same stack - by creating two stacks for the same directory. - */ - err = reftable_new_stack(&st1, dir, &opts); - EXPECT_ERR(err); - - err = reftable_new_stack(&st2, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st1, &write_test_ref, &ref1); - EXPECT_ERR(err); - - err = reftable_stack_add(st2, &write_test_ref, &ref2); - EXPECT(err == REFTABLE_OUTDATED_ERROR); - - err = reftable_stack_reload(st2); - EXPECT_ERR(err); - - err = reftable_stack_add(st2, &write_test_ref, &ref2); - EXPECT_ERR(err); - reftable_stack_destroy(st1); - reftable_stack_destroy(st2); - clear_dir(dir); -} - -static void test_reftable_stack_transaction_api(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err; - struct reftable_addition *add = NULL; - - struct reftable_ref_record ref = { - .refname = (char *) "HEAD", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - struct reftable_ref_record dest = { NULL }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - reftable_addition_destroy(add); - - err = reftable_stack_new_addition(&add, st); - EXPECT_ERR(err); - - err = reftable_addition_add(add, &write_test_ref, &ref); - EXPECT_ERR(err); - - err = reftable_addition_commit(add); - EXPECT_ERR(err); - - reftable_addition_destroy(add); - - err = reftable_stack_read_ref(st, ref.refname, &dest); - EXPECT_ERR(err); - EXPECT(REFTABLE_REF_SYMREF == dest.value_type); - EXPECT(0 == strcmp("master", dest.value.symref)); - - reftable_ref_record_release(&dest); - reftable_stack_destroy(st); - clear_dir(dir); -} - -static void test_reftable_stack_transaction_api_performs_auto_compaction(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = {0}; - struct reftable_addition *add = NULL; - struct reftable_stack *st = NULL; - int i, n = 20, err; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i <= n; i++) { - struct reftable_ref_record ref = { - .update_index = reftable_stack_next_update_index(st), - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - char name[100]; - - snprintf(name, sizeof(name), "branch%04d", i); - ref.refname = name; - - /* - * Disable auto-compaction for all but the last runs. Like this - * we can ensure that we indeed honor this setting and have - * better control over when exactly auto compaction runs. - */ - st->opts.disable_auto_compact = i != n; - - err = reftable_stack_new_addition(&add, st); - EXPECT_ERR(err); - - err = reftable_addition_add(add, &write_test_ref, &ref); - EXPECT_ERR(err); - - err = reftable_addition_commit(add); - EXPECT_ERR(err); - - reftable_addition_destroy(add); - - /* - * The stack length should grow continuously for all runs where - * auto compaction is disabled. When enabled, we should merge - * all tables in the stack. - */ - if (i != n) - EXPECT(st->merged->stack_len == i + 1); - else - EXPECT(st->merged->stack_len == 1); - } - - reftable_stack_destroy(st); - clear_dir(dir); -} - -static void test_reftable_stack_auto_compaction_fails_gracefully(void) -{ - struct reftable_ref_record ref = { - .refname = (char *) "refs/heads/master", - .update_index = 1, - .value_type = REFTABLE_REF_VAL1, - .value.val1 = {0x01}, - }; - struct reftable_write_options opts = {0}; - struct reftable_stack *st; - struct strbuf table_path = STRBUF_INIT; - char *dir = get_tmp_dir(__LINE__); - int err; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st, write_test_ref, &ref); - EXPECT_ERR(err); - EXPECT(st->merged->stack_len == 1); - EXPECT(st->stats.attempts == 0); - EXPECT(st->stats.failures == 0); - - /* - * Lock the newly written table such that it cannot be compacted. - * Adding a new table to the stack should not be impacted by this, even - * though auto-compaction will now fail. - */ - strbuf_addf(&table_path, "%s/%s.lock", dir, st->readers[0]->name); - write_file_buf(table_path.buf, "", 0); - - ref.update_index = 2; - err = reftable_stack_add(st, write_test_ref, &ref); - EXPECT_ERR(err); - EXPECT(st->merged->stack_len == 2); - EXPECT(st->stats.attempts == 1); - EXPECT(st->stats.failures == 1); - - reftable_stack_destroy(st); - strbuf_release(&table_path); - clear_dir(dir); -} - -static int write_error(struct reftable_writer *wr, void *arg) -{ - return *((int *)arg); -} - -static void test_reftable_stack_update_index_check(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err; - struct reftable_ref_record ref1 = { - .refname = (char *) "name1", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - struct reftable_ref_record ref2 = { - .refname = (char *) "name2", - .update_index = 1, - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st, &write_test_ref, &ref1); - EXPECT_ERR(err); - - err = reftable_stack_add(st, &write_test_ref, &ref2); - EXPECT(err == REFTABLE_API_ERROR); - reftable_stack_destroy(st); - clear_dir(dir); -} - -static void test_reftable_stack_lock_failure(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err, i; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) { - err = reftable_stack_add(st, &write_error, &i); - EXPECT(err == i); - } - - reftable_stack_destroy(st); - clear_dir(dir); -} - -static void test_reftable_stack_add(void) -{ - int i = 0; - int err = 0; - struct reftable_write_options opts = { - .exact_log_message = 1, - .default_permissions = 0660, - .disable_auto_compact = 1, - }; - struct reftable_stack *st = NULL; - char *dir = get_tmp_dir(__LINE__); - struct reftable_ref_record refs[2] = { { NULL } }; - struct reftable_log_record logs[2] = { { NULL } }; - struct strbuf path = STRBUF_INIT; - struct stat stat_result; - int N = ARRAY_SIZE(refs); - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i < N; i++) { - char buf[256]; - snprintf(buf, sizeof(buf), "branch%02d", i); - refs[i].refname = xstrdup(buf); - refs[i].update_index = i + 1; - refs[i].value_type = REFTABLE_REF_VAL1; - set_test_hash(refs[i].value.val1, i); - - logs[i].refname = xstrdup(buf); - logs[i].update_index = N + i + 1; - logs[i].value_type = REFTABLE_LOG_UPDATE; - logs[i].value.update.email = xstrdup("identity@invalid"); - set_test_hash(logs[i].value.update.new_hash, i); - } - - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, &write_test_ref, &refs[i]); - EXPECT_ERR(err); - } - - for (i = 0; i < N; i++) { - struct write_log_arg arg = { - .log = &logs[i], - .update_index = reftable_stack_next_update_index(st), - }; - int err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT_ERR(err); - } - - err = reftable_stack_compact_all(st, NULL); - EXPECT_ERR(err); - - for (i = 0; i < N; i++) { - struct reftable_ref_record dest = { NULL }; - - int err = reftable_stack_read_ref(st, refs[i].refname, &dest); - EXPECT_ERR(err); - EXPECT(reftable_ref_record_equal(&dest, refs + i, - GIT_SHA1_RAWSZ)); - reftable_ref_record_release(&dest); - } - - for (i = 0; i < N; i++) { - struct reftable_log_record dest = { NULL }; - int err = reftable_stack_read_log(st, refs[i].refname, &dest); - EXPECT_ERR(err); - EXPECT(reftable_log_record_equal(&dest, logs + i, - GIT_SHA1_RAWSZ)); - reftable_log_record_release(&dest); - } - -#ifndef GIT_WINDOWS_NATIVE - strbuf_addstr(&path, dir); - strbuf_addstr(&path, "/tables.list"); - err = stat(path.buf, &stat_result); - EXPECT(!err); - EXPECT((stat_result.st_mode & 0777) == opts.default_permissions); - - strbuf_reset(&path); - strbuf_addstr(&path, dir); - strbuf_addstr(&path, "/"); - /* do not try at home; not an external API for reftable. */ - strbuf_addstr(&path, st->readers[0]->name); - err = stat(path.buf, &stat_result); - EXPECT(!err); - EXPECT((stat_result.st_mode & 0777) == opts.default_permissions); -#else - (void) stat_result; -#endif - - /* cleanup */ - reftable_stack_destroy(st); - for (i = 0; i < N; i++) { - reftable_ref_record_release(&refs[i]); - reftable_log_record_release(&logs[i]); - } - strbuf_release(&path); - clear_dir(dir); -} - -static void test_reftable_stack_log_normalize(void) -{ - int err = 0; - struct reftable_write_options opts = { - 0, - }; - struct reftable_stack *st = NULL; - char *dir = get_tmp_dir(__LINE__); - struct reftable_log_record input = { - .refname = (char *) "branch", - .update_index = 1, - .value_type = REFTABLE_LOG_UPDATE, - .value = { - .update = { - .new_hash = { 1 }, - .old_hash = { 2 }, - }, - }, - }; - struct reftable_log_record dest = { - .update_index = 0, - }; - struct write_log_arg arg = { - .log = &input, - .update_index = 1, - }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - input.value.update.message = (char *) "one\ntwo"; - err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT(err == REFTABLE_API_ERROR); - - input.value.update.message = (char *) "one"; - err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT_ERR(err); - - err = reftable_stack_read_log(st, input.refname, &dest); - EXPECT_ERR(err); - EXPECT(0 == strcmp(dest.value.update.message, "one\n")); - - input.value.update.message = (char *) "two\n"; - arg.update_index = 2; - err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT_ERR(err); - err = reftable_stack_read_log(st, input.refname, &dest); - EXPECT_ERR(err); - EXPECT(0 == strcmp(dest.value.update.message, "two\n")); - - /* cleanup */ - reftable_stack_destroy(st); - reftable_log_record_release(&dest); - clear_dir(dir); -} - -static void test_reftable_stack_tombstone(void) -{ - int i = 0; - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err; - struct reftable_ref_record refs[2] = { { NULL } }; - struct reftable_log_record logs[2] = { { NULL } }; - int N = ARRAY_SIZE(refs); - struct reftable_ref_record dest = { NULL }; - struct reftable_log_record log_dest = { NULL }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - /* even entries add the refs, odd entries delete them. */ - for (i = 0; i < N; i++) { - const char *buf = "branch"; - refs[i].refname = xstrdup(buf); - refs[i].update_index = i + 1; - if (i % 2 == 0) { - refs[i].value_type = REFTABLE_REF_VAL1; - set_test_hash(refs[i].value.val1, i); - } - - logs[i].refname = xstrdup(buf); - /* update_index is part of the key. */ - logs[i].update_index = 42; - if (i % 2 == 0) { - logs[i].value_type = REFTABLE_LOG_UPDATE; - set_test_hash(logs[i].value.update.new_hash, i); - logs[i].value.update.email = - xstrdup("identity@invalid"); - } - } - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, &write_test_ref, &refs[i]); - EXPECT_ERR(err); - } - - for (i = 0; i < N; i++) { - struct write_log_arg arg = { - .log = &logs[i], - .update_index = reftable_stack_next_update_index(st), - }; - int err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT_ERR(err); - } - - err = reftable_stack_read_ref(st, "branch", &dest); - EXPECT(err == 1); - reftable_ref_record_release(&dest); - - err = reftable_stack_read_log(st, "branch", &log_dest); - EXPECT(err == 1); - reftable_log_record_release(&log_dest); - - err = reftable_stack_compact_all(st, NULL); - EXPECT_ERR(err); - - err = reftable_stack_read_ref(st, "branch", &dest); - EXPECT(err == 1); - - err = reftable_stack_read_log(st, "branch", &log_dest); - EXPECT(err == 1); - reftable_ref_record_release(&dest); - reftable_log_record_release(&log_dest); - - /* cleanup */ - reftable_stack_destroy(st); - for (i = 0; i < N; i++) { - reftable_ref_record_release(&refs[i]); - reftable_log_record_release(&logs[i]); - } - clear_dir(dir); -} - -static void test_reftable_stack_hash_id(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err; - - struct reftable_ref_record ref = { - .refname = (char *) "master", - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "target", - .update_index = 1, - }; - struct reftable_write_options opts32 = { .hash_id = GIT_SHA256_FORMAT_ID }; - struct reftable_stack *st32 = NULL; - struct reftable_write_options opts_default = { 0 }; - struct reftable_stack *st_default = NULL; - struct reftable_ref_record dest = { NULL }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st, &write_test_ref, &ref); - EXPECT_ERR(err); - - /* can't read it with the wrong hash ID. */ - err = reftable_new_stack(&st32, dir, &opts32); - EXPECT(err == REFTABLE_FORMAT_ERROR); - - /* check that we can read it back with default opts too. */ - err = reftable_new_stack(&st_default, dir, &opts_default); - EXPECT_ERR(err); - - err = reftable_stack_read_ref(st_default, "master", &dest); - EXPECT_ERR(err); - - EXPECT(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ)); - reftable_ref_record_release(&dest); - reftable_stack_destroy(st); - reftable_stack_destroy(st_default); - clear_dir(dir); -} - -static void test_suggest_compaction_segment(void) -{ - uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 }; - struct segment min = - suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - EXPECT(min.start == 1); - EXPECT(min.end == 10); -} - -static void test_suggest_compaction_segment_nothing(void) -{ - uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 }; - struct segment result = - suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - EXPECT(result.start == result.end); -} - -static void test_reflog_expire(void) -{ - char *dir = get_tmp_dir(__LINE__); - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - struct reftable_log_record logs[20] = { { NULL } }; - int N = ARRAY_SIZE(logs) - 1; - int i = 0; - int err; - struct reftable_log_expiry_config expiry = { - .time = 10, - }; - struct reftable_log_record log = { NULL }; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - for (i = 1; i <= N; i++) { - char buf[256]; - snprintf(buf, sizeof(buf), "branch%02d", i); - - logs[i].refname = xstrdup(buf); - logs[i].update_index = i; - logs[i].value_type = REFTABLE_LOG_UPDATE; - logs[i].value.update.time = i; - logs[i].value.update.email = xstrdup("identity@invalid"); - set_test_hash(logs[i].value.update.new_hash, i); - } - - for (i = 1; i <= N; i++) { - struct write_log_arg arg = { - .log = &logs[i], - .update_index = reftable_stack_next_update_index(st), - }; - int err = reftable_stack_add(st, &write_test_log, &arg); - EXPECT_ERR(err); - } - - err = reftable_stack_compact_all(st, NULL); - EXPECT_ERR(err); - - err = reftable_stack_compact_all(st, &expiry); - EXPECT_ERR(err); - - err = reftable_stack_read_log(st, logs[9].refname, &log); - EXPECT(err == 1); - - err = reftable_stack_read_log(st, logs[11].refname, &log); - EXPECT_ERR(err); - - expiry.min_update_index = 15; - err = reftable_stack_compact_all(st, &expiry); - EXPECT_ERR(err); - - err = reftable_stack_read_log(st, logs[14].refname, &log); - EXPECT(err == 1); - - err = reftable_stack_read_log(st, logs[16].refname, &log); - EXPECT_ERR(err); - - /* cleanup */ - reftable_stack_destroy(st); - for (i = 0; i <= N; i++) { - reftable_log_record_release(&logs[i]); - } - clear_dir(dir); - reftable_log_record_release(&log); -} - -static int write_nothing(struct reftable_writer *wr, void *arg) -{ - reftable_writer_set_limits(wr, 1, 1); - return 0; -} - -static void test_empty_add(void) -{ - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - int err; - char *dir = get_tmp_dir(__LINE__); - struct reftable_stack *st2 = NULL; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_add(st, &write_nothing, NULL); - EXPECT_ERR(err); - - err = reftable_new_stack(&st2, dir, &opts); - EXPECT_ERR(err); - clear_dir(dir); - reftable_stack_destroy(st); - reftable_stack_destroy(st2); -} - -static int fastlog2(uint64_t sz) -{ - int l = 0; - if (sz == 0) - return 0; - for (; sz; sz /= 2) - l++; - return l - 1; -} - -static void test_reftable_stack_auto_compaction(void) -{ - struct reftable_write_options opts = { - .disable_auto_compact = 1, - }; - struct reftable_stack *st = NULL; - char *dir = get_tmp_dir(__LINE__); - int err, i; - int N = 100; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i < N; i++) { - char name[100]; - struct reftable_ref_record ref = { - .refname = name, - .update_index = reftable_stack_next_update_index(st), - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - snprintf(name, sizeof(name), "branch%04d", i); - - err = reftable_stack_add(st, &write_test_ref, &ref); - EXPECT_ERR(err); - - err = reftable_stack_auto_compact(st); - EXPECT_ERR(err); - EXPECT(i < 3 || st->merged->stack_len < 2 * fastlog2(i)); - } - - EXPECT(reftable_stack_compaction_stats(st)->entries_written < - (uint64_t)(N * fastlog2(N))); - - reftable_stack_destroy(st); - clear_dir(dir); -} - -static void test_reftable_stack_add_performs_auto_compaction(void) -{ - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st = NULL; - struct strbuf refname = STRBUF_INIT; - char *dir = get_tmp_dir(__LINE__); - int err, i, n = 20; - - err = reftable_new_stack(&st, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i <= n; i++) { - struct reftable_ref_record ref = { - .update_index = reftable_stack_next_update_index(st), - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - - /* - * Disable auto-compaction for all but the last runs. Like this - * we can ensure that we indeed honor this setting and have - * better control over when exactly auto compaction runs. - */ - st->opts.disable_auto_compact = i != n; - - strbuf_reset(&refname); - strbuf_addf(&refname, "branch-%04d", i); - ref.refname = refname.buf; - - err = reftable_stack_add(st, &write_test_ref, &ref); - EXPECT_ERR(err); - - /* - * The stack length should grow continuously for all runs where - * auto compaction is disabled. When enabled, we should merge - * all tables in the stack. - */ - if (i != n) - EXPECT(st->merged->stack_len == i + 1); - else - EXPECT(st->merged->stack_len == 1); - } - - reftable_stack_destroy(st); - strbuf_release(&refname); - clear_dir(dir); -} - -static void test_reftable_stack_compaction_concurrent(void) -{ - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st1 = NULL, *st2 = NULL; - char *dir = get_tmp_dir(__LINE__); - int err, i; - int N = 3; - - err = reftable_new_stack(&st1, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i < N; i++) { - char name[100]; - struct reftable_ref_record ref = { - .refname = name, - .update_index = reftable_stack_next_update_index(st1), - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - snprintf(name, sizeof(name), "branch%04d", i); - - err = reftable_stack_add(st1, &write_test_ref, &ref); - EXPECT_ERR(err); - } - - err = reftable_new_stack(&st2, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_compact_all(st1, NULL); - EXPECT_ERR(err); - - reftable_stack_destroy(st1); - reftable_stack_destroy(st2); - - EXPECT(count_dir_entries(dir) == 2); - clear_dir(dir); -} - -static void unclean_stack_close(struct reftable_stack *st) -{ - /* break abstraction boundary to simulate unclean shutdown. */ - int i = 0; - for (; i < st->readers_len; i++) { - reftable_reader_free(st->readers[i]); - } - st->readers_len = 0; - FREE_AND_NULL(st->readers); -} - -static void test_reftable_stack_compaction_concurrent_clean(void) -{ - struct reftable_write_options opts = { 0 }; - struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL; - char *dir = get_tmp_dir(__LINE__); - int err, i; - int N = 3; - - err = reftable_new_stack(&st1, dir, &opts); - EXPECT_ERR(err); - - for (i = 0; i < N; i++) { - char name[100]; - struct reftable_ref_record ref = { - .refname = name, - .update_index = reftable_stack_next_update_index(st1), - .value_type = REFTABLE_REF_SYMREF, - .value.symref = (char *) "master", - }; - snprintf(name, sizeof(name), "branch%04d", i); - - err = reftable_stack_add(st1, &write_test_ref, &ref); - EXPECT_ERR(err); - } - - err = reftable_new_stack(&st2, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_compact_all(st1, NULL); - EXPECT_ERR(err); - - unclean_stack_close(st1); - unclean_stack_close(st2); - - err = reftable_new_stack(&st3, dir, &opts); - EXPECT_ERR(err); - - err = reftable_stack_clean(st3); - EXPECT_ERR(err); - EXPECT(count_dir_entries(dir) == 2); - - reftable_stack_destroy(st1); - reftable_stack_destroy(st2); - reftable_stack_destroy(st3); - - clear_dir(dir); -} - -int stack_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_empty_add); - RUN_TEST(test_read_file); - RUN_TEST(test_reflog_expire); - RUN_TEST(test_reftable_stack_add); - RUN_TEST(test_reftable_stack_add_one); - RUN_TEST(test_reftable_stack_auto_compaction); - RUN_TEST(test_reftable_stack_add_performs_auto_compaction); - RUN_TEST(test_reftable_stack_compaction_concurrent); - RUN_TEST(test_reftable_stack_compaction_concurrent_clean); - RUN_TEST(test_reftable_stack_hash_id); - RUN_TEST(test_reftable_stack_lock_failure); - RUN_TEST(test_reftable_stack_log_normalize); - RUN_TEST(test_reftable_stack_tombstone); - RUN_TEST(test_reftable_stack_transaction_api); - RUN_TEST(test_reftable_stack_transaction_api_performs_auto_compaction); - RUN_TEST(test_reftable_stack_auto_compaction_fails_gracefully); - RUN_TEST(test_reftable_stack_update_index_check); - RUN_TEST(test_reftable_stack_uptodate); - RUN_TEST(test_suggest_compaction_segment); - RUN_TEST(test_suggest_compaction_segment_nothing); - return 0; -} diff --git a/reftable/system.c b/reftable/system.c new file mode 100644 index 0000000000..adf8e4d30b --- /dev/null +++ b/reftable/system.c @@ -0,0 +1,126 @@ +#include "system.h" +#include "basics.h" +#include "reftable-error.h" +#include "../lockfile.h" +#include "../tempfile.h" + +int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern) +{ + struct tempfile *tempfile; + + tempfile = mks_tempfile(pattern); + if (!tempfile) + return REFTABLE_IO_ERROR; + + out->path = tempfile->filename.buf; + out->fd = tempfile->fd; + out->priv = tempfile; + + return 0; +} + +int tmpfile_close(struct reftable_tmpfile *t) +{ + struct tempfile *tempfile = t->priv; + int ret = close_tempfile_gently(tempfile); + t->fd = -1; + if (ret < 0) + return REFTABLE_IO_ERROR; + return 0; +} + +int tmpfile_delete(struct reftable_tmpfile *t) +{ + struct tempfile *tempfile = t->priv; + int ret = delete_tempfile(&tempfile); + *t = REFTABLE_TMPFILE_INIT; + if (ret < 0) + return REFTABLE_IO_ERROR; + return 0; +} + +int tmpfile_rename(struct reftable_tmpfile *t, const char *path) +{ + struct tempfile *tempfile = t->priv; + int ret = rename_tempfile(&tempfile, path); + *t = REFTABLE_TMPFILE_INIT; + if (ret < 0) + return REFTABLE_IO_ERROR; + return 0; +} + +int flock_acquire(struct reftable_flock *l, const char *target_path, + long timeout_ms) +{ + struct lock_file *lockfile; + int err; + + lockfile = reftable_malloc(sizeof(*lockfile)); + if (!lockfile) + return REFTABLE_OUT_OF_MEMORY_ERROR; + + err = hold_lock_file_for_update_timeout(lockfile, target_path, LOCK_NO_DEREF, + timeout_ms); + if (err < 0) { + reftable_free(lockfile); + if (errno == EEXIST) + return REFTABLE_LOCK_ERROR; + return -1; + } + + l->fd = get_lock_file_fd(lockfile); + l->path = get_lock_file_path(lockfile); + l->priv = lockfile; + + return 0; +} + +int flock_close(struct reftable_flock *l) +{ + struct lock_file *lockfile = l->priv; + int ret; + + if (!lockfile) + return REFTABLE_API_ERROR; + + ret = close_lock_file_gently(lockfile); + l->fd = -1; + if (ret < 0) + return REFTABLE_IO_ERROR; + + return 0; +} + +int flock_release(struct reftable_flock *l) +{ + struct lock_file *lockfile = l->priv; + int ret; + + if (!lockfile) + return 0; + + ret = rollback_lock_file(lockfile); + reftable_free(lockfile); + *l = REFTABLE_FLOCK_INIT; + if (ret < 0) + return REFTABLE_IO_ERROR; + + return 0; +} + +int flock_commit(struct reftable_flock *l) +{ + struct lock_file *lockfile = l->priv; + int ret; + + if (!lockfile) + return REFTABLE_API_ERROR; + + ret = commit_lock_file(lockfile); + reftable_free(lockfile); + *l = REFTABLE_FLOCK_INIT; + if (ret < 0) + return REFTABLE_IO_ERROR; + + return 0; +} diff --git a/reftable/system.h b/reftable/system.h index d0cabd5d17..7d5f803eeb 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -12,12 +12,90 @@ https://developers.google.com/open-source/licenses/bsd /* This header glues the reftable library to the rest of Git */ #include "git-compat-util.h" -#include "lockfile.h" -#include "strbuf.h" -#include "tempfile.h" -#include "hash.h" /* hash ID, sizes.*/ -#include "dir.h" /* remove_dir_recursively, for tests.*/ -int hash_size(uint32_t id); +/* + * An implementation-specific temporary file. By making this specific to the + * implementation it becomes possible to tie temporary files into any kind of + * signal or atexit handlers for cleanup on abnormal situations. + */ +struct reftable_tmpfile { + const char *path; + int fd; + void *priv; +}; +#define REFTABLE_TMPFILE_INIT ((struct reftable_tmpfile) { .fd = -1, }) + +/* + * Create a temporary file from a pattern similar to how mkstemp(3p) would. + * The `pattern` shall not be modified. On success, the structure at `out` has + * been initialized such that it is ready for use. Returns 0 on success, a + * reftable error code on error. + */ +int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern); + +/* + * Close the temporary file's file descriptor without removing the file itself. + * This is a no-op in case the file has already been closed beforehand. Returns + * 0 on success, a reftable error code on error. + */ +int tmpfile_close(struct reftable_tmpfile *t); + +/* + * Close the temporary file and delete it. This is a no-op in case the file has + * already been deleted or renamed beforehand. Returns 0 on success, a reftable + * error code on error. + */ +int tmpfile_delete(struct reftable_tmpfile *t); + +/* + * Rename the temporary file to the provided path. The temporary file must be + * active. Return 0 on success, a reftable error code on error. Deactivates the + * temporary file. + */ +int tmpfile_rename(struct reftable_tmpfile *t, const char *path); + +/* + * An implementation-specific file lock. Same as with `reftable_tmpfile`, + * making this specific to the implementation makes it possible to tie this + * into signal or atexit handlers such that we know to clean up stale locks on + * abnormal exits. + */ +struct reftable_flock { + const char *path; + int fd; + void *priv; +}; +#define REFTABLE_FLOCK_INIT ((struct reftable_flock){ .fd = -1, }) + +/* + * Acquire the lock for the given target path by exclusively creating a file + * with ".lock" appended to it. If that lock exists, we wait up to `timeout_ms` + * to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative + * we block indefinitely. + * + * Retrun 0 on success, a reftable error code on error. + */ +int flock_acquire(struct reftable_flock *l, const char *target_path, + long timeout_ms); + +/* + * Close the lockfile's file descriptor without removing the lock itself. This + * is a no-op in case the lockfile has already been closed beforehand. Returns + * 0 on success, a reftable error code on error. + */ +int flock_close(struct reftable_flock *l); + +/* + * Release the lock by unlinking the lockfile. This is a no-op in case the + * lockfile has already been released or committed beforehand. Returns 0 on + * success, a reftable error code on error. + */ +int flock_release(struct reftable_flock *l); + +/* + * Commit the lock by renaming the lockfile into place. Returns 0 on success, a + * reftable error code on error. + */ +int flock_commit(struct reftable_flock *l); #endif diff --git a/reftable/test_framework.c b/reftable/test_framework.c deleted file mode 100644 index 4066924eee..0000000000 --- a/reftable/test_framework.c +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" -#include "test_framework.h" - - -void set_test_hash(uint8_t *p, int i) -{ - memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID)); -} - -ssize_t strbuf_add_void(void *b, const void *data, size_t sz) -{ - strbuf_add(b, data, sz); - return sz; -} - -int noop_flush(void *arg) -{ - return 0; -} diff --git a/reftable/test_framework.h b/reftable/test_framework.h deleted file mode 100644 index 687390f9c2..0000000000 --- a/reftable/test_framework.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef TEST_FRAMEWORK_H -#define TEST_FRAMEWORK_H - -#include "system.h" -#include "reftable-error.h" - -#define EXPECT_ERR(c) \ - do { \ - if (c != 0) { \ - fflush(stderr); \ - fflush(stdout); \ - fprintf(stderr, "%s: %d: error == %d (%s), want 0\n", \ - __FILE__, __LINE__, c, reftable_error_str(c)); \ - abort(); \ - } \ - } while (0) - -#define EXPECT_STREQ(a, b) \ - do { \ - if (strcmp(a, b)) { \ - fflush(stderr); \ - fflush(stdout); \ - fprintf(stderr, "%s:%d: %s (%s) != %s (%s)\n", __FILE__, \ - __LINE__, #a, a, #b, b); \ - abort(); \ - } \ - } while (0) - -#define EXPECT(c) \ - do { \ - if (!(c)) { \ - fflush(stderr); \ - fflush(stdout); \ - fprintf(stderr, "%s: %d: failed assertion %s\n", __FILE__, \ - __LINE__, #c); \ - abort(); \ - } \ - } while (0) - -#define RUN_TEST(f) \ - fprintf(stderr, "running %s\n", #f); \ - fflush(stderr); \ - f(); - -void set_test_hash(uint8_t *p, int i); - -/* Like strbuf_add, but suitable for passing to reftable_new_writer - */ -ssize_t strbuf_add_void(void *b, const void *data, size_t sz); - -int noop_flush(void *); - -#endif diff --git a/reftable/tree.c b/reftable/tree.c index 528f33ae38..f4dbe72090 100644 --- a/reftable/tree.c +++ b/reftable/tree.c @@ -11,53 +11,64 @@ https://developers.google.com/open-source/licenses/bsd #include "basics.h" -struct tree_node *tree_search(void *key, struct tree_node **rootp, - int (*compare)(const void *, const void *), - int insert) +struct tree_node *tree_search(struct tree_node *tree, + void *key, + int (*compare)(const void *, const void *)) { int res; + if (!tree) + return NULL; + res = compare(key, tree->key); + if (res < 0) + return tree_search(tree->left, key, compare); + else if (res > 0) + return tree_search(tree->right, key, compare); + return tree; +} + +struct tree_node *tree_insert(struct tree_node **rootp, + void *key, + int (*compare)(const void *, const void *)) +{ + int res; + if (!*rootp) { - if (!insert) { + struct tree_node *n; + + REFTABLE_CALLOC_ARRAY(n, 1); + if (!n) return NULL; - } else { - struct tree_node *n; - REFTABLE_CALLOC_ARRAY(n, 1); - n->key = key; - *rootp = n; - return *rootp; - } + + n->key = key; + *rootp = n; + return *rootp; } res = compare(key, (*rootp)->key); if (res < 0) - return tree_search(key, &(*rootp)->left, compare, insert); + return tree_insert(&(*rootp)->left, key, compare); else if (res > 0) - return tree_search(key, &(*rootp)->right, compare, insert); + return tree_insert(&(*rootp)->right, key, compare); return *rootp; } void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key), void *arg) { - if (t->left) { + if (t->left) infix_walk(t->left, action, arg); - } action(arg, t->key); - if (t->right) { + if (t->right) infix_walk(t->right, action, arg); - } } void tree_free(struct tree_node *t) { - if (!t) { + if (!t) return; - } - if (t->left) { + if (t->left) tree_free(t->left); - } - if (t->right) { + if (t->right) tree_free(t->right); - } reftable_free(t); } diff --git a/reftable/tree.h b/reftable/tree.h index fbdd002e23..9604453b6d 100644 --- a/reftable/tree.h +++ b/reftable/tree.h @@ -15,12 +15,23 @@ struct tree_node { struct tree_node *left, *right; }; -/* looks for `key` in `rootp` using `compare` as comparison function. If insert - * is set, insert the key if it's not found. Else, return NULL. +/* + * Search the tree for the node matching the given key using `compare` as + * comparison function. Returns the node whose key matches or `NULL` in case + * the key does not exist in the tree. + */ +struct tree_node *tree_search(struct tree_node *tree, + void *key, + int (*compare)(const void *, const void *)); + +/* + * Insert a node into the tree. Returns the newly inserted node if the key does + * not yet exist. Otherwise it returns the preexisting node. Returns `NULL` + * when allocating the new node fails. */ -struct tree_node *tree_search(void *key, struct tree_node **rootp, - int (*compare)(const void *, const void *), - int insert); +struct tree_node *tree_insert(struct tree_node **rootp, + void *key, + int (*compare)(const void *, const void *)); /* performs an infix walk of the tree. */ void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key), diff --git a/reftable/tree_test.c b/reftable/tree_test.c deleted file mode 100644 index 6961a657ad..0000000000 --- a/reftable/tree_test.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" -#include "tree.h" - -#include "test_framework.h" -#include "reftable-tests.h" - -static int test_compare(const void *a, const void *b) -{ - return (char *)a - (char *)b; -} - -struct curry { - void *last; -}; - -static void check_increasing(void *arg, void *key) -{ - struct curry *c = arg; - if (c->last) { - EXPECT(test_compare(c->last, key) < 0); - } - c->last = key; -} - -static void test_tree(void) -{ - struct tree_node *root = NULL; - - void *values[11] = { NULL }; - struct tree_node *nodes[11] = { NULL }; - int i = 1; - struct curry c = { NULL }; - do { - nodes[i] = tree_search(values + i, &root, &test_compare, 1); - i = (i * 7) % 11; - } while (i != 1); - - for (i = 1; i < ARRAY_SIZE(nodes); i++) { - EXPECT(values + i == nodes[i]->key); - EXPECT(nodes[i] == - tree_search(values + i, &root, &test_compare, 0)); - } - - infix_walk(root, check_increasing, &c); - tree_free(root); -} - -int tree_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_tree); - return 0; -} diff --git a/reftable/writer.c b/reftable/writer.c index 45b3e9ce1f..9efeab13e1 100644 --- a/reftable/writer.c +++ b/reftable/writer.c @@ -49,8 +49,14 @@ static int padded_write(struct reftable_writer *w, uint8_t *data, size_t len, { int n = 0; if (w->pending_padding > 0) { - uint8_t *zeroed = reftable_calloc(w->pending_padding, sizeof(*zeroed)); - int n = w->write(w->write_arg, zeroed, w->pending_padding); + uint8_t *zeroed; + int n; + + zeroed = reftable_calloc(w->pending_padding, sizeof(*zeroed)); + if (!zeroed) + return -1; + + n = w->write(w->write_arg, zeroed, w->pending_padding); if (n < 0) return n; @@ -73,7 +79,7 @@ static void options_set_defaults(struct reftable_write_options *opts) } if (opts->hash_id == 0) { - opts->hash_id = GIT_SHA1_FORMAT_ID; + opts->hash_id = REFTABLE_HASH_SHA1; } if (opts->block_size == 0) { opts->block_size = DEFAULT_BLOCK_SIZE; @@ -82,7 +88,7 @@ static void options_set_defaults(struct reftable_write_options *opts) static int writer_version(struct reftable_writer *w) { - return (w->opts.hash_id == 0 || w->opts.hash_id == GIT_SHA1_FORMAT_ID) ? + return (w->opts.hash_id == 0 || w->opts.hash_id == REFTABLE_HASH_SHA1) ? 1 : 2; } @@ -97,33 +103,56 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest) put_be64(dest + 8, w->min_update_index); put_be64(dest + 16, w->max_update_index); if (writer_version(w) == 2) { - put_be32(dest + 24, w->opts.hash_id); + uint32_t hash_id; + + switch (w->opts.hash_id) { + case REFTABLE_HASH_SHA1: + hash_id = REFTABLE_FORMAT_ID_SHA1; + break; + case REFTABLE_HASH_SHA256: + hash_id = REFTABLE_FORMAT_ID_SHA256; + break; + default: + return -1; + } + + put_be32(dest + 24, hash_id); } + return header_size(writer_version(w)); } -static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ) +static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ) { - int block_start = 0; - if (w->next == 0) { + int block_start = 0, ret; + + if (w->next == 0) block_start = header_size(writer_version(w)); - } - strbuf_reset(&w->last_key); - block_writer_init(&w->block_writer_data, typ, w->block, - w->opts.block_size, block_start, - hash_size(w->opts.hash_id)); + reftable_buf_reset(&w->last_key); + ret = block_writer_init(&w->block_writer_data, typ, w->block, + w->opts.block_size, block_start, + hash_size(w->opts.hash_id)); + if (ret < 0) + return ret; + w->block_writer = &w->block_writer_data; w->block_writer->restart_interval = w->opts.restart_interval; + + return 0; } -struct reftable_writer * -reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t), - int (*flush_func)(void *), - void *writer_arg, const struct reftable_write_options *_opts) +int reftable_writer_new(struct reftable_writer **out, + ssize_t (*writer_func)(void *, const void *, size_t), + int (*flush_func)(void *), + void *writer_arg, const struct reftable_write_options *_opts) { - struct reftable_writer *wp = reftable_calloc(1, sizeof(*wp)); struct reftable_write_options opts = {0}; + struct reftable_writer *wp; + + wp = reftable_calloc(1, sizeof(*wp)); + if (!wp) + return REFTABLE_OUT_OF_MEMORY_ERROR; if (_opts) opts = *_opts; @@ -131,16 +160,23 @@ reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t), if (opts.block_size >= (1 << 24)) BUG("configured block size exceeds 16MB"); - strbuf_init(&wp->block_writer_data.last_key, 0); - strbuf_init(&wp->last_key, 0); + reftable_buf_init(&wp->block_writer_data.last_key); + reftable_buf_init(&wp->last_key); + reftable_buf_init(&wp->scratch); REFTABLE_CALLOC_ARRAY(wp->block, opts.block_size); + if (!wp->block) { + reftable_free(wp); + return REFTABLE_OUT_OF_MEMORY_ERROR; + } wp->write = writer_func; wp->write_arg = writer_arg; wp->opts = opts; wp->flush = flush_func; writer_reinit_block_writer(wp, BLOCK_TYPE_REF); - return wp; + *out = wp; + + return 0; } void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, @@ -158,7 +194,8 @@ static void writer_release(struct reftable_writer *w) block_writer_release(&w->block_writer_data); w->block_writer = NULL; writer_clear_index(w); - strbuf_release(&w->last_key); + reftable_buf_release(&w->last_key); + reftable_buf_release(&w->scratch); } } @@ -169,7 +206,7 @@ void reftable_writer_free(struct reftable_writer *w) } struct obj_index_tree_node { - struct strbuf hash; + struct reftable_buf hash; uint64_t *offsets; size_t offset_len; size_t offset_cap; @@ -177,61 +214,78 @@ struct obj_index_tree_node { #define OBJ_INDEX_TREE_NODE_INIT \ { \ - .hash = STRBUF_INIT \ + .hash = REFTABLE_BUF_INIT \ } static int obj_index_tree_node_compare(const void *a, const void *b) { - return strbuf_cmp(&((const struct obj_index_tree_node *)a)->hash, + return reftable_buf_cmp(&((const struct obj_index_tree_node *)a)->hash, &((const struct obj_index_tree_node *)b)->hash); } -static void writer_index_hash(struct reftable_writer *w, struct strbuf *hash) +static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *hash) { uint64_t off = w->next; - struct obj_index_tree_node want = { .hash = *hash }; + struct obj_index_tree_node *key; + struct tree_node *node; - struct tree_node *node = tree_search(&want, &w->obj_index_tree, - &obj_index_tree_node_compare, 0); - struct obj_index_tree_node *key = NULL; + node = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare); if (!node) { struct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT; - key = reftable_malloc(sizeof(struct obj_index_tree_node)); + int err; + + key = reftable_malloc(sizeof(*key)); + if (!key) + return REFTABLE_OUT_OF_MEMORY_ERROR; + *key = empty; - strbuf_reset(&key->hash); - strbuf_addbuf(&key->hash, hash); - tree_search((void *)key, &w->obj_index_tree, - &obj_index_tree_node_compare, 1); + reftable_buf_reset(&key->hash); + err = reftable_buf_add(&key->hash, hash->buf, hash->len); + if (err < 0) + return err; + tree_insert(&w->obj_index_tree, key, + &obj_index_tree_node_compare); } else { key = node->key; } - if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off) { - return; - } + if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off) + return 0; REFTABLE_ALLOC_GROW(key->offsets, key->offset_len + 1, key->offset_cap); + if (!key->offsets) + return REFTABLE_OUT_OF_MEMORY_ERROR; key->offsets[key->offset_len++] = off; + + return 0; } static int writer_add_record(struct reftable_writer *w, struct reftable_record *rec) { - struct strbuf key = STRBUF_INIT; int err; - reftable_record_key(rec, &key); - if (strbuf_cmp(&w->last_key, &key) >= 0) { + err = reftable_record_key(rec, &w->scratch); + if (err < 0) + goto done; + + if (reftable_buf_cmp(&w->last_key, &w->scratch) >= 0) { err = REFTABLE_API_ERROR; goto done; } - strbuf_reset(&w->last_key); - strbuf_addbuf(&w->last_key, &key); - if (!w->block_writer) - writer_reinit_block_writer(w, reftable_record_type(rec)); + reftable_buf_reset(&w->last_key); + err = reftable_buf_add(&w->last_key, w->scratch.buf, w->scratch.len); + if (err < 0) + goto done; + + if (!w->block_writer) { + err = writer_reinit_block_writer(w, reftable_record_type(rec)); + if (err < 0) + goto done; + } if (block_writer_type(w->block_writer) != reftable_record_type(rec)) BUG("record of type %d added to writer of type %d", @@ -254,7 +308,9 @@ static int writer_add_record(struct reftable_writer *w, err = writer_flush_block(w); if (err < 0) goto done; - writer_reinit_block_writer(w, reftable_record_type(rec)); + err = writer_reinit_block_writer(w, reftable_record_type(rec)); + if (err < 0) + goto done; /* * Try to add the record to the writer again. If this still fails then @@ -271,7 +327,6 @@ static int writer_add_record(struct reftable_writer *w, } done: - strbuf_release(&key); return err; } @@ -284,11 +339,10 @@ int reftable_writer_add_ref(struct reftable_writer *w, .ref = *ref }, }; - int err = 0; + int err; - if (!ref->refname) - return REFTABLE_API_ERROR; - if (ref->update_index < w->min_update_index || + if (!ref->refname || + ref->update_index < w->min_update_index || ref->update_index > w->max_update_index) return REFTABLE_API_ERROR; @@ -296,24 +350,36 @@ int reftable_writer_add_ref(struct reftable_writer *w, err = writer_add_record(w, &rec); if (err < 0) - return err; + goto out; if (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) { - struct strbuf h = STRBUF_INIT; - strbuf_add(&h, (char *)reftable_ref_record_val1(ref), - hash_size(w->opts.hash_id)); - writer_index_hash(w, &h); - strbuf_release(&h); + reftable_buf_reset(&w->scratch); + err = reftable_buf_add(&w->scratch, (char *)reftable_ref_record_val1(ref), + hash_size(w->opts.hash_id)); + if (err < 0) + goto out; + + err = writer_index_hash(w, &w->scratch); + if (err < 0) + goto out; } if (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) { - struct strbuf h = STRBUF_INIT; - strbuf_add(&h, reftable_ref_record_val2(ref), - hash_size(w->opts.hash_id)); - writer_index_hash(w, &h); - strbuf_release(&h); + reftable_buf_reset(&w->scratch); + err = reftable_buf_add(&w->scratch, reftable_ref_record_val2(ref), + hash_size(w->opts.hash_id)); + if (err < 0) + goto out; + + err = writer_index_hash(w, &w->scratch); + if (err < 0) + goto out; } - return 0; + + err = 0; + +out: + return err; } int reftable_writer_add_refs(struct reftable_writer *w, @@ -353,7 +419,7 @@ int reftable_writer_add_log(struct reftable_writer *w, struct reftable_log_record *log) { char *input_log_message = NULL; - struct strbuf cleaned_message = STRBUF_INIT; + struct reftable_buf cleaned_message = REFTABLE_BUF_INIT; int err = 0; if (log->value_type == REFTABLE_LOG_DELETION) @@ -364,24 +430,34 @@ int reftable_writer_add_log(struct reftable_writer *w, input_log_message = log->value.update.message; if (!w->opts.exact_log_message && log->value.update.message) { - strbuf_addstr(&cleaned_message, log->value.update.message); + err = reftable_buf_addstr(&cleaned_message, log->value.update.message); + if (err < 0) + goto done; + while (cleaned_message.len && - cleaned_message.buf[cleaned_message.len - 1] == '\n') - strbuf_setlen(&cleaned_message, - cleaned_message.len - 1); + cleaned_message.buf[cleaned_message.len - 1] == '\n') { + err = reftable_buf_setlen(&cleaned_message, + cleaned_message.len - 1); + if (err < 0) + goto done; + } if (strchr(cleaned_message.buf, '\n')) { /* multiple lines not allowed. */ err = REFTABLE_API_ERROR; goto done; } - strbuf_addstr(&cleaned_message, "\n"); + + err = reftable_buf_addstr(&cleaned_message, "\n"); + if (err < 0) + goto done; + log->value.update.message = cleaned_message.buf; } err = reftable_writer_add_log_verbatim(w, log); log->value.update.message = input_log_message; done: - strbuf_release(&cleaned_message); + reftable_buf_release(&cleaned_message); return err; } @@ -436,7 +512,9 @@ static int writer_finish_section(struct reftable_writer *w) max_level++; index_start = w->next; - writer_reinit_block_writer(w, BLOCK_TYPE_INDEX); + err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX); + if (err < 0) + return err; idx = w->index; idx_len = w->index_len; @@ -462,7 +540,7 @@ static int writer_finish_section(struct reftable_writer *w) return err; for (i = 0; i < idx_len; i++) - strbuf_release(&idx[i].last_key); + reftable_buf_release(&idx[i].last_key); reftable_free(idx); } @@ -479,13 +557,13 @@ static int writer_finish_section(struct reftable_writer *w) bstats->max_index_level = max_level; /* Reinit lastKey, as the next section can start with any key. */ - strbuf_reset(&w->last_key); + reftable_buf_reset(&w->last_key); return 0; } struct common_prefix_arg { - struct strbuf *last; + struct reftable_buf *last; int max; }; @@ -530,7 +608,10 @@ static void write_object_record(void *void_arg, void *key) if (arg->err < 0) goto done; - writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ); + arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ); + if (arg->err < 0) + goto done; + arg->err = block_writer_add(arg->w->block_writer, &rec); if (arg->err == 0) goto done; @@ -544,12 +625,12 @@ static void write_object_record(void *void_arg, void *key) done:; } -static void object_record_free(void *void_arg, void *key) +static void object_record_free(void *void_arg UNUSED, void *key) { struct obj_index_tree_node *entry = key; - FREE_AND_NULL(entry->offsets); - strbuf_release(&entry->hash); + REFTABLE_FREE_AND_NULL(entry->offsets); + reftable_buf_release(&entry->hash); reftable_free(entry); } @@ -559,16 +640,18 @@ static int writer_dump_object_index(struct reftable_writer *w) struct common_prefix_arg common = { .max = 1, /* obj_id_len should be >= 2. */ }; - if (w->obj_index_tree) { + int err; + + if (w->obj_index_tree) infix_walk(w->obj_index_tree, &update_common, &common); - } w->stats.object_id_len = common.max + 1; - writer_reinit_block_writer(w, BLOCK_TYPE_OBJ); + err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ); + if (err < 0) + return err; - if (w->obj_index_tree) { + if (w->obj_index_tree) infix_walk(w->obj_index_tree, &write_object_record, &closure); - } if (closure.err < 0) return closure.err; @@ -661,8 +744,8 @@ done: static void writer_clear_index(struct reftable_writer *w) { for (size_t i = 0; w->index && i < w->index_len; i++) - strbuf_release(&w->index[i].last_key); - FREE_AND_NULL(w->index); + reftable_buf_release(&w->index[i].last_key); + REFTABLE_FREE_AND_NULL(w->index); w->index_len = 0; w->index_cap = 0; } @@ -670,7 +753,7 @@ static void writer_clear_index(struct reftable_writer *w) static int writer_flush_nonempty_block(struct reftable_writer *w) { struct reftable_index_record index_record = { - .last_key = STRBUF_INIT, + .last_key = REFTABLE_BUF_INIT, }; uint8_t typ = block_writer_type(w->block_writer); struct reftable_block_stats *bstats; @@ -726,9 +809,15 @@ static int writer_flush_nonempty_block(struct reftable_writer *w) * case we will end up with a multi-level index. */ REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap); + if (!w->index) + return REFTABLE_OUT_OF_MEMORY_ERROR; + index_record.offset = w->next; - strbuf_reset(&index_record.last_key); - strbuf_addbuf(&index_record.last_key, &w->block_writer->last_key); + reftable_buf_reset(&index_record.last_key); + err = reftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf, + w->block_writer->last_key.len); + if (err < 0) + return err; w->index[w->index_len] = index_record; w->index_len++; diff --git a/reftable/writer.h b/reftable/writer.h index 8d0df9cc52..1f4788a430 100644 --- a/reftable/writer.h +++ b/reftable/writer.h @@ -19,7 +19,9 @@ struct reftable_writer { int (*flush)(void *); void *write_arg; int pending_padding; - struct strbuf last_key; + struct reftable_buf last_key; + /* Scratch buffer used to avoid allocations. */ + struct reftable_buf scratch; /* offset of next block to write. */ uint64_t next; diff --git a/remote-curl.c b/remote-curl.c index 4adcf25ed6..9a71e04301 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -347,7 +347,7 @@ static struct ref *parse_info_refs(struct discovery *heads) ref->next = refs; refs = ref; } else { - free(ref); + free_one_ref(ref); } return refs; @@ -24,6 +24,7 @@ #include "advice.h" #include "connect.h" #include "parse-options.h" +#include "transport.h" enum map_direction { FROM_SRC, FROM_DST }; @@ -143,6 +144,7 @@ static struct remote *make_remote(struct remote_state *remote_state, ret->name = xstrndup(name, len); refspec_init(&ret->push, REFSPEC_PUSH); refspec_init(&ret->fetch, REFSPEC_FETCH); + string_list_init_dup(&ret->server_options); ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1, remote_state->remotes_alloc); @@ -166,6 +168,7 @@ static void remote_clear(struct remote *remote) free((char *)remote->uploadpack); FREE_AND_NULL(remote->http_proxy); FREE_AND_NULL(remote->http_proxy_authmethod); + string_list_clear(&remote->server_options, 0); } static void add_merge(struct branch *branch, const char *name) @@ -243,6 +246,17 @@ static struct branch *make_branch(struct remote_state *remote_state, return ret; } +static void branch_release(struct branch *branch) +{ + free((char *)branch->name); + free((char *)branch->refname); + free(branch->remote_name); + free(branch->pushremote_name); + for (int i = 0; i < branch->merge_nr; i++) + refspec_item_clear(branch->merge[i]); + free(branch->merge); +} + static struct rewrite *make_rewrite(struct rewrites *r, const char *base, size_t len) { @@ -263,6 +277,14 @@ static struct rewrite *make_rewrite(struct rewrites *r, return ret; } +static void rewrites_release(struct rewrites *r) +{ + for (int i = 0; i < r->rewrite_nr; i++) + free((char *)r->rewrite[i]->base); + free(r->rewrite); + memset(r, 0, sizeof(*r)); +} + static void add_instead_of(struct rewrite *rewrite, const char *instead_of) { ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc); @@ -373,8 +395,10 @@ static int handle_config(const char *key, const char *value, return -1; branch = make_branch(remote_state, name, namelen); if (!strcmp(subkey, "remote")) { + FREE_AND_NULL(branch->remote_name); return git_config_string(&branch->remote_name, key, value); } else if (!strcmp(subkey, "pushremote")) { + FREE_AND_NULL(branch->pushremote_name); return git_config_string(&branch->pushremote_name, key, value); } else if (!strcmp(subkey, "merge")) { if (!value) @@ -406,9 +430,11 @@ static int handle_config(const char *key, const char *value, return 0; /* Handle remote.* variables */ - if (!name && !strcmp(subkey, "pushdefault")) + if (!name && !strcmp(subkey, "pushdefault")) { + FREE_AND_NULL(remote_state->pushremote_name); return git_config_string(&remote_state->pushremote_name, key, value); + } if (!name) return 0; @@ -475,13 +501,19 @@ static int handle_config(const char *key, const char *value, else if (!strcmp(value, "--tags")) remote->fetch_tags = 2; } else if (!strcmp(subkey, "proxy")) { + FREE_AND_NULL(remote->http_proxy); return git_config_string(&remote->http_proxy, key, value); } else if (!strcmp(subkey, "proxyauthmethod")) { + FREE_AND_NULL(remote->http_proxy_authmethod); return git_config_string(&remote->http_proxy_authmethod, key, value); } else if (!strcmp(subkey, "vcs")) { + FREE_AND_NULL(remote->foreign_vcs); return git_config_string(&remote->foreign_vcs, key, value); + } else if (!strcmp(subkey, "serveroption")) { + return parse_transport_option(key, value, + &remote->server_options); } return 0; } @@ -499,6 +531,7 @@ static void alias_all_urls(struct remote_state *remote_state) if (alias) strvec_replace(&remote_state->remotes[i]->pushurl, j, alias); + free(alias); } add_pushurl_aliases = remote_state->remotes[i]->pushurl.nr == 0; for (j = 0; j < remote_state->remotes[i]->url.nr; j++) { @@ -512,6 +545,7 @@ static void alias_all_urls(struct remote_state *remote_state) if (alias) strvec_replace(&remote_state->remotes[i]->url, j, alias); + free(alias); } } } @@ -604,7 +638,7 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit) static struct remote *remotes_remote_get(struct remote_state *remote_state, const char *name); -const char *remote_ref_for_branch(struct branch *branch, int for_push) +char *remote_ref_for_branch(struct branch *branch, int for_push) { read_config(the_repository, 0); die_on_missing_branch(the_repository, branch); @@ -612,11 +646,11 @@ const char *remote_ref_for_branch(struct branch *branch, int for_push) if (branch) { if (!for_push) { if (branch->merge_nr) { - return branch->merge_name[0]; + return xstrdup(branch->merge_name[0]); } } else { - const char *dst, - *remote_name = remotes_pushremote_for_branch( + char *dst; + const char *remote_name = remotes_pushremote_for_branch( the_repository->remote_state, branch, NULL); struct remote *remote = remotes_remote_get( @@ -840,6 +874,20 @@ struct strvec *push_url_of_remote(struct remote *remote) return remote->pushurl.nr ? &remote->pushurl : &remote->url; } +void ref_push_report_free(struct ref_push_report *report) +{ + while (report) { + struct ref_push_report *next = report->next; + + free(report->ref_name); + free(report->old_oid); + free(report->new_oid); + free(report); + + report = next; + } +} + static int match_name_with_pattern(const char *key, const char *name, const char *value, char **result) { @@ -1094,7 +1142,9 @@ void free_one_ref(struct ref *ref) if (!ref) return; free_one_ref(ref->peer_ref); + ref_push_report_free(ref->report); free(ref->remote_status); + free(ref->tracking_ref); free(ref->symref); free(ref); } @@ -1316,18 +1366,21 @@ static int match_explicit(struct ref *src, struct ref *dst, struct ref ***dst_tail, struct refspec_item *rs) { - struct ref *matched_src, *matched_dst; - int allocated_src; + struct ref *matched_src = NULL, *matched_dst = NULL; + int allocated_src = 0, ret; const char *dst_value = rs->dst; char *dst_guess; - if (rs->pattern || rs->matching || rs->negative) - return 0; + if (rs->pattern || rs->matching || rs->negative) { + ret = 0; + goto out; + } - matched_src = matched_dst = NULL; - if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0) - return -1; + if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0) { + ret = -1; + goto out; + } if (!dst_value) { int flag; @@ -1366,18 +1419,30 @@ static int match_explicit(struct ref *src, struct ref *dst, dst_value); break; } - if (!matched_dst) - return -1; - if (matched_dst->peer_ref) - return error(_("dst ref %s receives from more than one src"), - matched_dst->name); - else { + + if (!matched_dst) { + ret = -1; + goto out; + } + + if (matched_dst->peer_ref) { + ret = error(_("dst ref %s receives from more than one src"), + matched_dst->name); + goto out; + } else { matched_dst->peer_ref = allocated_src ? matched_src : copy_ref(matched_src); matched_dst->force = rs->force; + matched_src = NULL; } - return 0; + + ret = 0; + +out: + if (allocated_src) + free_one_ref(matched_src); + return ret; } static int match_explicit_refs(struct ref *src, struct ref *dst, @@ -2038,6 +2103,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs, !ignore_symref_update(expn_name, &scratch)) { struct ref *cpy = copy_ref(ref); + if (cpy->peer_ref) + free_one_ref(cpy->peer_ref); cpy->peer_ref = alloc_ref(expn_name); if (refspec->force) cpy->peer_ref->force = 1; @@ -2354,7 +2421,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb, return 1; } -static int one_local_ref(const char *refname, const struct object_id *oid, +static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -2439,7 +2506,7 @@ struct stale_heads_info { struct refspec *rs; }; -static int get_stale_heads_cb(const char *refname, const struct object_id *oid, +static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags, void *cb_data) { struct stale_heads_info *info = cb_data; @@ -2498,7 +2565,7 @@ struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map) /* * Compare-and-swap */ -static void clear_cas_option(struct push_cas_option *cas) +void clear_cas_option(struct push_cas_option *cas) { int i; @@ -2575,8 +2642,10 @@ static int remote_tracking(struct remote *remote, const char *refname, dst = apply_refspecs(&remote->fetch, refname); if (!dst) return -1; /* no tracking ref for refname at remote */ - if (refs_read_ref(get_main_ref_store(the_repository), dst, oid)) + if (refs_read_ref(get_main_ref_store(the_repository), dst, oid)) { + free(dst); return -1; /* we know what the tracking ref is but we cannot read it */ + } *dst_refname = dst; return 0; @@ -2726,6 +2795,7 @@ static void check_if_includes_upstream(struct ref *remote) if (is_reachable_in_reflog(local->name, remote) <= 0) remote->unreachable = 1; + free_one_ref(local); } static void apply_cas(struct push_cas_option *cas, @@ -2795,16 +2865,26 @@ struct remote_state *remote_state_new(void) void remote_state_clear(struct remote_state *remote_state) { + struct hashmap_iter iter; + struct branch *b; int i; for (i = 0; i < remote_state->remotes_nr; i++) remote_clear(remote_state->remotes[i]); FREE_AND_NULL(remote_state->remotes); + FREE_AND_NULL(remote_state->pushremote_name); remote_state->remotes_alloc = 0; remote_state->remotes_nr = 0; + rewrites_release(&remote_state->rewrites); + rewrites_release(&remote_state->rewrites_push); + hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent); - hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent); + hashmap_for_each_entry(&remote_state->branches_hash, &iter, b, ent) { + branch_release(b); + free(b); + } + hashmap_clear(&remote_state->branches_hash); } /* @@ -4,6 +4,7 @@ #include "hash.h" #include "hashmap.h" #include "refspec.h" +#include "string-list.h" #include "strvec.h" struct option; @@ -104,6 +105,8 @@ struct remote { /* The method used for authenticating against `http_proxy`. */ char *http_proxy_authmethod; + + struct string_list server_options; }; /** @@ -126,13 +129,15 @@ int remote_has_url(struct remote *remote, const char *url); struct strvec *push_url_of_remote(struct remote *remote); struct ref_push_report { - const char *ref_name; + char *ref_name; struct object_id *old_oid; struct object_id *new_oid; unsigned int forced_update:1; struct ref_push_report *next; }; +void ref_push_report_free(struct ref_push_report *); + struct ref { struct ref *next; struct object_id old_oid; @@ -329,7 +334,7 @@ struct branch { struct branch *branch_get(const char *name); const char *remote_for_branch(struct branch *branch, int *explicit); const char *pushremote_for_branch(struct branch *branch, int *explicit); -const char *remote_ref_for_branch(struct branch *branch, int for_push); +char *remote_ref_for_branch(struct branch *branch, int for_push); /* returns true if the given branch has merge configuration given. */ int branch_has_merge_config(struct branch *branch); @@ -409,6 +414,7 @@ struct push_cas_option { }; int parseopt_push_cas_option(const struct option *, const char *arg, int unset); +void clear_cas_option(struct push_cas_option *); int is_empty_cas(const struct push_cas_option *); void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *); diff --git a/replace-object.c b/replace-object.c index 59252d565e..9a3cdd809a 100644 --- a/replace-object.c +++ b/replace-object.c @@ -9,6 +9,7 @@ #include "commit.h" static int register_replace_ref(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) diff --git a/repo-settings.c b/repo-settings.c index 2b4e68731b..9d16d5399e 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -1,7 +1,9 @@ #include "git-compat-util.h" #include "config.h" +#include "repo-settings.h" #include "repository.h" #include "midx.h" +#include "pack-objects.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) @@ -19,22 +21,22 @@ 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; int manyfiles; int read_changed_paths; + unsigned long ulongval; if (!r->gitdir) BUG("Cannot add settings for uninitialized repository"); - if (r->settings.initialized++) + if (r->settings.initialized) return; - /* Defaults */ - r->settings.index_version = -1; - r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP; - r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE; + memcpy(&r->settings, &defaults, sizeof(defaults)); + r->settings.initialized++; /* Booleans config or default, cascades to other settings */ repo_cfg_bool(r, "feature.manyfiles", &manyfiles, 0); @@ -123,4 +125,45 @@ void prepare_repo_settings(struct repository *r) * removed. */ r->settings.command_requires_full_index = 1; + + if (!repo_config_get_ulong(r, "core.deltabasecachelimit", &ulongval)) + r->settings.delta_base_cache_limit = ulongval; + + if (!repo_config_get_ulong(r, "core.packedgitwindowsize", &ulongval)) { + int pgsz_x2 = getpagesize() * 2; + + /* This value must be multiple of (pagesize * 2) */ + ulongval /= pgsz_x2; + if (ulongval < 1) + ulongval = 1; + r->settings.packed_git_window_size = ulongval * pgsz_x2; + } + + if (!repo_config_get_ulong(r, "core.packedgitlimit", &ulongval)) + r->settings.packed_git_limit = ulongval; +} + +enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) +{ + const char *value; + + if (!repo_config_get_string_tmp(repo, "core.logallrefupdates", &value)) { + if (value && !strcasecmp(value, "always")) + return LOG_REFS_ALWAYS; + else if (git_config_bool("core.logallrefupdates", value)) + return LOG_REFS_NORMAL; + else + return LOG_REFS_NONE; + } + + return LOG_REFS_UNSET; +} + +int repo_settings_get_warn_ambiguous_refs(struct repository *repo) +{ + prepare_repo_settings(repo); + if (repo->settings.warn_ambiguous_refs < 0) + repo_cfg_bool(repo, "core.warnambiguousrefs", + &repo->settings.warn_ambiguous_refs, 1); + return repo->settings.warn_ambiguous_refs; } diff --git a/repo-settings.h b/repo-settings.h new file mode 100644 index 0000000000..93ea0c3274 --- /dev/null +++ b/repo-settings.h @@ -0,0 +1,82 @@ +#ifndef REPO_SETTINGS_H +#define REPO_SETTINGS_H + +struct fsmonitor_settings; +struct repository; + +enum untracked_cache_setting { + UNTRACKED_CACHE_KEEP, + UNTRACKED_CACHE_REMOVE, + UNTRACKED_CACHE_WRITE, +}; + +enum fetch_negotiation_setting { + FETCH_NEGOTIATION_CONSECUTIVE, + FETCH_NEGOTIATION_SKIPPING, + FETCH_NEGOTIATION_NOOP, +}; + +enum log_refs_config { + LOG_REFS_UNSET = -1, + LOG_REFS_NONE = 0, + LOG_REFS_NORMAL, + LOG_REFS_ALWAYS +}; + +struct repo_settings { + int initialized; + + int core_commit_graph; + int commit_graph_generation_version; + int commit_graph_changed_paths_version; + int gc_write_commit_graph; + int fetch_write_commit_graph; + int command_requires_full_index; + int sparse_index; + int pack_read_reverse_index; + int pack_use_bitmap_boundary_traversal; + int pack_use_multi_pack_reuse; + + /* + * Does this repository have core.useReplaceRefs=true (on by + * default)? This provides a repository-scoped version of this + * config, though it could be disabled process-wide via some Git + * builtins or the --no-replace-objects option. See + * replace_refs_enabled() for more details. + */ + int read_replace_refs; + + struct fsmonitor_settings *fsmonitor; /* lazily loaded */ + + int index_version; + int index_skip_hash; + enum untracked_cache_setting core_untracked_cache; + + int pack_use_sparse; + enum fetch_negotiation_setting fetch_negotiation_algorithm; + + int core_multi_pack_index; + int warn_ambiguous_refs; /* lazily loaded via accessor */ + + size_t delta_base_cache_limit; + size_t packed_git_window_size; + size_t packed_git_limit; +}; +#define REPO_SETTINGS_INIT { \ + .index_version = -1, \ + .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ + .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ + .warn_ambiguous_refs = -1, \ + .delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT, \ + .packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE, \ + .packed_git_limit = DEFAULT_PACKED_GIT_LIMIT, \ +} + +void prepare_repo_settings(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); + +#endif /* REPO_SETTINGS_H */ diff --git a/repository.c b/repository.c index 9825a30899..1a6a62bbd0 100644 --- a/repository.c +++ b/repository.c @@ -54,7 +54,7 @@ void initialize_repository(struct repository *repo) { repo->objects = raw_object_store_new(); repo->remote_state = remote_state_new(); - repo->parsed_objects = parsed_object_pool_new(); + repo->parsed_objects = parsed_object_pool_new(repo); ALLOC_ARRAY(repo->index, 1); index_state_init(repo->index, repo); @@ -91,6 +91,46 @@ static void expand_base_dir(char **out, const char *in, *out = xstrfmt("%s/%s", base_dir, def_in); } +const char *repo_get_git_dir(struct repository *repo) +{ + if (!repo->gitdir) + BUG("repository hasn't been set up"); + return repo->gitdir; +} + +const char *repo_get_common_dir(struct repository *repo) +{ + if (!repo->commondir) + BUG("repository hasn't been set up"); + return repo->commondir; +} + +const char *repo_get_object_directory(struct repository *repo) +{ + if (!repo->objects->odb) + BUG("repository hasn't been set up"); + return repo->objects->odb->path; +} + +const char *repo_get_index_file(struct repository *repo) +{ + if (!repo->index_file) + BUG("repository hasn't been set up"); + return repo->index_file; +} + +const char *repo_get_graft_file(struct repository *repo) +{ + if (!repo->graft_file) + BUG("repository hasn't been set up"); + return repo->graft_file; +} + +const char *repo_get_work_tree(struct repository *repo) +{ + return repo->worktree; +} + static void repo_set_commondir(struct repository *repo, const char *commondir) { @@ -243,6 +283,7 @@ int repo_init(struct repository *repo, repo_set_compat_hash_algo(repo, format.compat_hash_algo); repo_set_ref_storage_format(repo, format.ref_storage_format); repo->repository_format_worktree_config = format.worktree_config; + repo->repository_format_relative_worktrees = format.relative_worktrees; /* take ownership of format.partial_clone */ repo->repository_format_partial_clone = format.partial_clone; diff --git a/repository.h b/repository.h index af6ea0a62c..c4c92b2ab9 100644 --- a/repository.h +++ b/repository.h @@ -2,9 +2,9 @@ #define REPOSITORY_H #include "strmap.h" +#include "repo-settings.h" struct config_set; -struct fsmonitor_settings; struct git_hash_algo; struct index_state; struct lock_file; @@ -14,59 +14,12 @@ struct submodule_cache; struct promisor_remote_config; struct remote_state; -enum untracked_cache_setting { - UNTRACKED_CACHE_KEEP, - UNTRACKED_CACHE_REMOVE, - UNTRACKED_CACHE_WRITE, -}; - -enum fetch_negotiation_setting { - FETCH_NEGOTIATION_CONSECUTIVE, - FETCH_NEGOTIATION_SKIPPING, - FETCH_NEGOTIATION_NOOP, -}; - enum ref_storage_format { REF_STORAGE_FORMAT_UNKNOWN, REF_STORAGE_FORMAT_FILES, REF_STORAGE_FORMAT_REFTABLE, }; -struct repo_settings { - int initialized; - - int core_commit_graph; - int commit_graph_generation_version; - int commit_graph_changed_paths_version; - int gc_write_commit_graph; - int fetch_write_commit_graph; - int command_requires_full_index; - int sparse_index; - int pack_read_reverse_index; - int pack_use_bitmap_boundary_traversal; - int pack_use_multi_pack_reuse; - - /* - * Does this repository have core.useReplaceRefs=true (on by - * default)? This provides a repository-scoped version of this - * config, though it could be disabled process-wide via some Git - * builtins or the --no-replace-objects option. See - * replace_refs_enabled() for more details. - */ - int read_replace_refs; - - struct fsmonitor_settings *fsmonitor; /* lazily loaded */ - - int index_version; - int index_skip_hash; - enum untracked_cache_setting core_untracked_cache; - - int pack_use_sparse; - enum fetch_negotiation_setting fetch_negotiation_algorithm; - - int core_multi_pack_index; -}; - struct repo_path_cache { char *squash_msg; char *merge_msg; @@ -197,6 +150,7 @@ struct repository { /* Configurations */ int repository_format_worktree_config; + int repository_format_relative_worktrees; /* Indicate if a repository has a different 'commondir' from 'gitdir' */ unsigned different_commondir:1; @@ -206,6 +160,13 @@ struct repository { extern struct repository *the_repository; #endif +const char *repo_get_git_dir(struct repository *repo); +const char *repo_get_common_dir(struct repository *repo); +const char *repo_get_object_directory(struct repository *repo); +const char *repo_get_index_file(struct repository *repo); +const char *repo_get_graft_file(struct repository *repo); +const char *repo_get_work_tree(struct repository *repo); + /* * Define a custom repository layout. Any field can be NULL, which * will default back to the path according to the default layout. @@ -266,8 +227,6 @@ int repo_read_index_unmerged(struct repository *); */ void repo_update_index_if_able(struct repository *, struct lock_file *); -void prepare_repo_settings(struct repository *r); - /* * Return 1 if upgrade repository format to target_version succeeded, * 0 if no upgrade is necessary, and -1 when upgrade is not possible. @@ -1208,8 +1208,10 @@ void rerere_gc(struct repository *r, struct string_list *rr) if (setup_rerere(r, rr, 0) < 0) return; - git_config_get_expiry_in_days("gc.rerereresolved", &cutoff_resolve, now); - git_config_get_expiry_in_days("gc.rerereunresolved", &cutoff_noresolve, now); + repo_config_get_expiry_in_days(the_repository, "gc.rerereresolved", + &cutoff_resolve, now); + 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")); if (!dir) @@ -79,7 +79,7 @@ static int update_refs(const struct reset_head_opts *opts, reflog_head); } if (!ret && run_hook) - run_hooks_l("post-checkout", + run_hooks_l(the_repository, "post-checkout", oid_to_hex(head ? head : null_oid()), oid_to_hex(oid), "1", NULL); strbuf_release(&msg); diff --git a/revision.c b/revision.c index 1c0192f522..57ca521c55 100644 --- a/revision.c +++ b/revision.c @@ -51,8 +51,8 @@ volatile show_early_output_fn_t show_early_output; -static const char *term_bad; -static const char *term_good; +static char *term_bad; +static char *term_good; implement_shared_commit_slab(revision_sources, char *); @@ -390,7 +390,8 @@ static struct object *get_reference(struct rev_info *revs, const char *name, if (!object) { if (revs->ignore_missing) return NULL; - if (revs->exclude_promisor_objects && is_promisor_object(oid)) + if (revs->exclude_promisor_objects && + is_promisor_object(revs->repo, oid)) return NULL; if (revs->do_not_die_on_missing_objects) { oidset_insert(&revs->missing_commits, oid); @@ -432,7 +433,7 @@ static struct commit *handle_commit(struct rev_info *revs, if (revs->ignore_missing_links || (flags & UNINTERESTING)) return NULL; if (revs->exclude_promisor_objects && - is_promisor_object(&tag->tagged->oid)) + is_promisor_object(revs->repo, &tag->tagged->oid)) return NULL; if (revs->do_not_die_on_missing_objects && oid) { oidset_insert(&revs->missing_commits, oid); @@ -1071,7 +1072,11 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) ts->treesame[nth_parent] = 1; continue; } + + free_commit_list(parent->next); parent->next = NULL; + while (commit->parents != parent) + pop_commit(&commit->parents); commit->parents = parent; /* @@ -1103,6 +1108,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) die("cannot simplify commit %s (invalid %s)", oid_to_hex(&commit->object.oid), oid_to_hex(&p->object.oid)); + free_commit_list(p->parents); p->parents = NULL; } /* fallthrough */ @@ -1206,7 +1212,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit, revs->do_not_die_on_missing_objects; if (repo_parse_commit_gently(revs->repo, p, gently) < 0) { if (revs->exclude_promisor_objects && - is_promisor_object(&p->object.oid)) { + is_promisor_object(revs->repo, &p->object.oid)) { if (revs->first_parent_only) break; continue; @@ -1648,7 +1654,7 @@ struct all_refs_cb { struct worktree *wt; }; -static int handle_one_ref(const char *path, const struct object_id *oid, +static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -1872,7 +1878,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags) continue; /* current index already taken care of */ if (read_index_from(&istate, - worktree_git_path(wt, "index"), + worktree_git_path(the_repository, wt, "index"), get_worktree_git_dir(wt)) > 0) do_add_index_objects_to_pending(revs, &istate, flags); discard_index(&istate); @@ -3222,6 +3228,11 @@ void release_revisions(struct rev_info *revs) clear_decoration(&revs->treesame, free); line_log_free(revs); oidset_clear(&revs->missing_commits); + + for (int i = 0; i < revs->bloom_keys_nr; i++) + clear_bloom_key(&revs->bloom_keys[i]); + FREE_AND_NULL(revs->bloom_keys); + revs->bloom_keys_nr = 0; } static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child) @@ -3245,6 +3256,7 @@ static int remove_duplicate_parents(struct rev_info *revs, struct commit *commit struct commit *parent = p->item; if (parent->object.flags & TMP_MARK) { *pp = p->next; + free(p); if (ts) compact_treesame(revs, commit, surviving_parents); continue; @@ -3909,7 +3921,7 @@ int prepare_revision_walk(struct rev_info *revs) revs->treesame.name = "treesame"; if (revs->exclude_promisor_objects) { - for_each_packed_object(mark_uninteresting, revs, + for_each_packed_object(revs->repo, mark_uninteresting, revs, FOR_EACH_OBJECT_PROMISOR_ONLY); } @@ -4000,6 +4012,7 @@ int rewrite_parents(struct rev_info *revs, struct commit *commit, break; case rewrite_one_noparents: *pp = parent->next; + free(parent); continue; case rewrite_one_error: return -1; @@ -4096,10 +4109,10 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi { if (commit->object.flags & SHOWN) return commit_ignore; - if (revs->unpacked && has_object_pack(&commit->object.oid)) + if (revs->unpacked && has_object_pack(revs->repo, &commit->object.oid)) return commit_ignore; if (revs->no_kept_objects) { - if (has_object_kept_pack(&commit->object.oid, + if (has_object_kept_pack(revs->repo, &commit->object.oid, revs->keep_pack_cache_flags)) return commit_ignore; } @@ -4200,10 +4213,18 @@ static void save_parents(struct rev_info *revs, struct commit *commit) *pp = EMPTY_PARENT_LIST; } +static void free_saved_parent(struct commit_list **parents) +{ + if (*parents != EMPTY_PARENT_LIST) + free_commit_list(*parents); +} + static void free_saved_parents(struct rev_info *revs) { - if (revs->saved_parents_slab) - clear_saved_parents(revs->saved_parents_slab); + if (!revs->saved_parents_slab) + return; + deep_clear_saved_parents(revs->saved_parents_slab, free_saved_parent); + FREE_AND_NULL(revs->saved_parents_slab); } struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit) @@ -4407,6 +4428,7 @@ static struct commit *get_revision_internal(struct rev_info *revs) c = get_revision_1(revs); if (!c) break; + free_commit_buffer(revs->repo->parsed_objects, c); } } diff --git a/revision.h b/revision.h index 0e470d1df1..71e984c452 100644 --- a/revision.h +++ b/revision.h @@ -549,7 +549,7 @@ int rewrite_parents(struct rev_info *revs, * The log machinery saves the original parent list so that * get_saved_parents() can later tell what the real parents of the * commits are, when commit->parents has been modified by history - * simpification. + * simplification. * * get_saved_parents() will transparently return commit->parents if * history simplification is off. diff --git a/run-command.c b/run-command.c index 45ba544932..94f2f3079f 100644 --- a/run-command.c +++ b/run-command.c @@ -1808,16 +1808,26 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) int prepare_auto_maintenance(int quiet, struct child_process *maint) { - int enabled; + int enabled, auto_detach; if (!git_config_get_bool("maintenance.auto", &enabled) && !enabled) return 0; + /* + * When `maintenance.autoDetach` isn't set, then we fall back to + * honoring `gc.autoDetach`. This is somewhat weird, but required to + * retain behaviour from when we used to run git-gc(1) here. + */ + if (git_config_get_bool("maintenance.autodetach", &auto_detach) && + git_config_get_bool("gc.autodetach", &auto_detach)) + auto_detach = 1; + maint->git_cmd = 1; maint->close_object_store = 1; strvec_pushl(&maint->args, "maintenance", "run", "--auto", NULL); strvec_push(&maint->args, quiet ? "--quiet" : "--no-quiet"); + strvec_push(&maint->args, auto_detach ? "--detach" : "--no-detach"); return 1; } diff --git a/run-command.h b/run-command.h index 03e7222d8b..0df25e445f 100644 --- a/run-command.h +++ b/run-command.h @@ -535,7 +535,7 @@ enum start_bg_result { /* timeout expired waiting for child to become "ready" */ SBGR_TIMEOUT, - /* child process exited or was signalled before becomming "ready" */ + /* child process exited or was signalled before becoming "ready" */ SBGR_DIED, }; @@ -400,7 +400,8 @@ static int delete_enlistment(struct strbuf *enlistment) * Dummy implementation; Using `get_version_info()` would cause a link error * without this. */ -void load_builtin_commands(const char *prefix, struct cmdnames *cmds) +void load_builtin_commands(const char *prefix UNUSED, + struct cmdnames *cmds UNUSED) { die("not implemented"); } @@ -409,7 +410,7 @@ static int cmd_clone(int argc, const char **argv) { const char *branch = NULL; int full_clone = 0, single_branch = 0, show_progress = isatty(2); - int src = 1; + int src = 1, tags = 1; struct option clone_options[] = { OPT_STRING('b', "branch", &branch, N_("<branch>"), N_("branch to checkout after clone")), @@ -420,11 +421,13 @@ static int cmd_clone(int argc, const char **argv) "be checked out")), OPT_BOOL(0, "src", &src, N_("create repository within 'src' directory")), + OPT_BOOL(0, "tags", &tags, + N_("specify if tags should be fetched during clone")), OPT_END(), }; const char * const clone_usage[] = { N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" - "\t[--[no-]src] <url> [<enlistment>]"), + "\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]"), NULL }; const char *url; @@ -503,6 +506,11 @@ static int cmd_clone(int argc, const char **argv) goto cleanup; } + if (!tags && set_config("remote.origin.tagOpt=--no-tags")) { + res = error(_("could not disable tags in '%s'"), dir); + goto cleanup; + } + if (!full_clone && (res = run_git("sparse-checkout", "init", "--cone", NULL))) goto cleanup; @@ -512,7 +520,9 @@ static int cmd_clone(int argc, const char **argv) if ((res = run_git("fetch", "--quiet", show_progress ? "--progress" : "--no-progress", - "origin", NULL))) { + "origin", + (tags ? NULL : "--no-tags"), + NULL))) { warning(_("partial clone failed; attempting full clone")); if (set_config("remote.origin.promisor") || @@ -722,6 +732,10 @@ static int cmd_reconfigure(int argc, const char **argv) succeeded = 1; the_repository = old_repo; + repo_clear(&r); + + if (toggle_maintenance(1) >= 0) + succeeded = 1; loop_end: if (!succeeded) { diff --git a/send-pack.c b/send-pack.c index fa2f5eec17..6677c44e8a 100644 --- a/send-pack.c +++ b/send-pack.c @@ -75,6 +75,7 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, int i; int rc; + trace2_region_enter("send_pack", "pack_objects", the_repository); strvec_push(&po.args, "pack-objects"); strvec_push(&po.args, "--all-progress-implied"); strvec_push(&po.args, "--revs"); @@ -146,8 +147,10 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised, */ if (rc > 128 && rc != 141) error("pack-objects died of signal %d", rc - 128); + trace2_region_leave("send_pack", "pack_objects", the_repository); return -1; } + trace2_region_leave("send_pack", "pack_objects", the_repository); return 0; } @@ -170,6 +173,7 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) int new_report = 0; int once = 0; + trace2_region_enter("send_pack", "receive_status", the_repository); hint = NULL; ret = receive_unpack_status(reader); while (1) { @@ -268,6 +272,7 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) new_report = 1; } } + trace2_region_leave("send_pack", "receive_status", the_repository); return ret; } @@ -348,7 +353,8 @@ static int generate_push_cert(struct strbuf *req_buf, { const struct ref *ref; struct string_list_item *item; - char *signing_key_id = xstrdup(get_signing_key_id()); + char *signing_key_id = get_signing_key_id(); + char *signing_key = get_signing_key(); const char *cp, *np; struct strbuf cert = STRBUF_INIT; int update_seen = 0; @@ -381,7 +387,7 @@ static int generate_push_cert(struct strbuf *req_buf, if (!update_seen) goto free_return; - if (sign_buffer(&cert, &cert, get_signing_key())) + if (sign_buffer(&cert, &cert, signing_key)) die(_("failed to sign the push certificate")); packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string); @@ -394,6 +400,7 @@ static int generate_push_cert(struct strbuf *req_buf, free_return: free(signing_key_id); + free(signing_key); strbuf_release(&cert); return update_seen; } @@ -501,19 +508,23 @@ int send_pack(struct send_pack_args *args, unsigned cmds_sent = 0; int ret; struct async demux; - const char *push_cert_nonce = NULL; + char *push_cert_nonce = NULL; struct packet_reader reader; int use_bitmaps; if (!remote_refs) { fprintf(stderr, "No refs in common and none specified; doing nothing.\n" "Perhaps you should specify a branch.\n"); - return 0; + ret = 0; + goto out; } git_config_get_bool("push.negotiate", &push_negotiate); - if (push_negotiate) + if (push_negotiate) { + trace2_region_enter("send_pack", "push_negotiate", the_repository); get_commons_through_negotiation(args->url, remote_refs, &commons); + trace2_region_leave("send_pack", "push_negotiate", the_repository); + } if (!git_config_get_bool("push.usebitmaps", &use_bitmaps)) args->disable_bitmaps = !use_bitmaps; @@ -549,10 +560,11 @@ int send_pack(struct send_pack_args *args, if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) { size_t len; - push_cert_nonce = server_feature_value("push-cert", &len); - if (push_cert_nonce) { - reject_invalid_nonce(push_cert_nonce, len); - push_cert_nonce = xmemdupz(push_cert_nonce, len); + const char *nonce = server_feature_value("push-cert", &len); + + if (nonce) { + reject_invalid_nonce(nonce, len); + push_cert_nonce = xmemdupz(nonce, len); } else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) { die(_("the receiving end does not support --signed push")); } else if (args->push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) { @@ -615,12 +627,11 @@ int send_pack(struct send_pack_args *args, * atomically, abort the whole operation. */ if (use_atomic) { - strbuf_release(&req_buf); - strbuf_release(&cap_buf); reject_atomic_push(remote_refs, args->send_mirror); - error("atomic push failed for ref %s. status: %d\n", + error("atomic push failed for ref %s. status: %d", ref->name, ref->status); - return args->porcelain ? 0 : -1; + ret = args->porcelain ? 0 : -1; + goto out; } /* else fallthrough */ default: @@ -641,10 +652,11 @@ int send_pack(struct send_pack_args *args, /* * Finally, tell the other end! */ - if (!args->dry_run && push_cert_nonce) + if (!args->dry_run && push_cert_nonce) { cmds_sent = generate_push_cert(&req_buf, remote_refs, args, cap_buf.buf, push_cert_nonce); - else if (!args->dry_run) + trace2_printf("Generated push certificate"); + } else if (!args->dry_run) { for (ref = remote_refs; ref; ref = ref->next) { char *old_hex, *new_hex; @@ -664,6 +676,7 @@ int send_pack(struct send_pack_args *args, old_hex, new_hex, ref->name); } } + } if (use_push_options) { struct string_list_item *item; @@ -682,8 +695,6 @@ int send_pack(struct send_pack_args *args, write_or_die(out, req_buf.buf, req_buf.len); packet_flush(out); } - strbuf_release(&req_buf); - strbuf_release(&cap_buf); if (use_sideband && cmds_sent) { memset(&demux, 0, sizeof(demux)); @@ -721,7 +732,9 @@ int send_pack(struct send_pack_args *args, finish_async(&demux); } fd[1] = -1; - return -1; + + ret = -1; + goto out; } if (!args->stateless_rpc) /* Closed by pack_objects() via start_command() */ @@ -746,10 +759,12 @@ int send_pack(struct send_pack_args *args, } if (ret < 0) - return ret; + goto out; - if (args->porcelain) - return 0; + if (args->porcelain) { + ret = 0; + goto out; + } for (ref = remote_refs; ref; ref = ref->next) { switch (ref->status) { @@ -758,8 +773,17 @@ int send_pack(struct send_pack_args *args, case REF_STATUS_OK: break; default: - return -1; + ret = -1; + goto out; } } - return 0; + + ret = 0; + +out: + oid_array_clear(&commons); + strbuf_release(&req_buf); + strbuf_release(&cap_buf); + free(push_cert_nonce); + return ret; } diff --git a/sequencer.c b/sequencer.c index a2284ac9e9..459066e43b 100644 --- a/sequencer.c +++ b/sequencer.c @@ -303,6 +303,7 @@ static int git_sequencer_config(const char *k, const char *v, } if (!strcmp(k, "commit.gpgsign")) { + free(opts->gpg_sign); opts->gpg_sign = git_config_bool(k, v) ? xstrdup("") : NULL; return 0; } @@ -661,7 +662,7 @@ static int fast_forward_to(struct repository *r, strbuf_addf(&sb, "%s: fast-forward", action_name(opts)); transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction || ref_transaction_update(transaction, "HEAD", to, unborn && !is_rebase_i(opts) ? @@ -762,7 +763,7 @@ static int do_recursive_merge(struct repository *r, repo_read_index(r); - init_merge_options(&o, r); + init_ui_merge_options(&o, r); o.ancestor = base ? base_label : "(empty tree)"; o.branch1 = "HEAD"; o.branch2 = next ? next_label : "(empty tree)"; @@ -1296,7 +1297,7 @@ int update_head_with_reflog(const struct commit *old_head, } transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - err); + 0, err); if (!transaction || ref_transaction_update(transaction, "HEAD", new_head, old_head ? &old_head->object.oid : null_oid(), @@ -1316,7 +1317,7 @@ static int run_rewrite_hook(const struct object_id *oldoid, struct child_process proc = CHILD_PROCESS_INIT; int code; struct strbuf sb = STRBUF_INIT; - const char *hook_path = find_hook("post-rewrite"); + const char *hook_path = find_hook(the_repository, "post-rewrite"); if (!hook_path) return 0; @@ -1614,7 +1615,7 @@ static int try_to_commit(struct repository *r, } } - if (hook_exists("prepare-commit-msg")) { + if (hook_exists(r, "prepare-commit-msg")) { res = run_prepare_commit_msg_hook(r, msg, hook_commit); if (res) goto out; @@ -1940,10 +1941,10 @@ static int seen_squash(struct replay_ctx *ctx) static void update_comment_bufs(struct strbuf *buf1, struct strbuf *buf2, int n) { - strbuf_setlen(buf1, 2); + strbuf_setlen(buf1, strlen(comment_line_str) + 1); strbuf_addf(buf1, _(nth_commit_msg_fmt), n); strbuf_addch(buf1, '\n'); - strbuf_setlen(buf2, 2); + strbuf_setlen(buf2, strlen(comment_line_str) + 1); strbuf_addf(buf2, _(skip_nth_commit_msg_fmt), n); strbuf_addch(buf2, '\n'); } @@ -1962,8 +1963,12 @@ static void update_squash_message_for_fixup(struct strbuf *msg) size_t orig_msg_len; int i = 1; - strbuf_addf(&buf1, "# %s\n", _(first_commit_msg_str)); - strbuf_addf(&buf2, "# %s\n", _(skip_first_commit_msg_str)); + strbuf_add_commented_lines(&buf1, _(first_commit_msg_str), + strlen(_(first_commit_msg_str)), + comment_line_str); + strbuf_add_commented_lines(&buf2, _(skip_first_commit_msg_str), + strlen(_(skip_first_commit_msg_str)), + comment_line_str); s = start = orig_msg = strbuf_detach(msg, &orig_msg_len); while (s) { const char *next; @@ -2340,8 +2345,8 @@ static int do_pick_commit(struct repository *r, next = parent; next_label = msg.parent_label; if (opts->commit_use_reference) { - strbuf_addstr(&ctx->message, - "# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***"); + strbuf_commented_addf(&ctx->message, comment_line_str, + "*** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***"); } else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) && /* * We don't touch pre-existing repeated reverts, because @@ -2351,12 +2356,13 @@ static int do_pick_commit(struct repository *r, !starts_with(orig_subject, "Revert \"")) { strbuf_addstr(&ctx->message, "Reapply \""); strbuf_addstr(&ctx->message, orig_subject); + strbuf_addstr(&ctx->message, "\n"); } else { strbuf_addstr(&ctx->message, "Revert \""); strbuf_addstr(&ctx->message, msg.subject); - strbuf_addstr(&ctx->message, "\""); + strbuf_addstr(&ctx->message, "\"\n"); } - strbuf_addstr(&ctx->message, "\n\nThis reverts commit "); + strbuf_addstr(&ctx->message, "\nThis reverts commit "); refer_to_commit(opts, &ctx->message, commit); if (commit->parents && commit->parents->next) { @@ -3793,12 +3799,13 @@ static int error_failed_squash(struct repository *r, return error_with_patch(r, commit, subject, subject_len, opts, 1, 0); } -static int do_exec(struct repository *r, const char *command_line) +static int do_exec(struct repository *r, const char *command_line, int quiet) { struct child_process cmd = CHILD_PROCESS_INIT; int dirty, status; - fprintf(stderr, _("Executing: %s\n"), command_line); + if (!quiet) + fprintf(stderr, _("Executing: %s\n"), command_line); cmd.use_shell = 1; strvec_push(&cmd.args, command_line); strvec_push(&cmd.env, "GIT_CHERRY_PICK_HELP"); @@ -3888,7 +3895,7 @@ static int do_label(struct repository *r, const char *name, int len) strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name); strbuf_addf(&msg, "rebase (label) '%.*s'", len, name); - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction) { error("%s", err.buf); ret = -1; @@ -4309,7 +4316,7 @@ static int do_merge(struct repository *r, bases = reverse_commit_list(bases); repo_read_index(r); - init_merge_options(&o, r); + init_ui_merge_options(&o, r); o.branch1 = "HEAD"; o.branch2 = ref_name.buf; o.buffer_output = 2; @@ -5013,7 +5020,7 @@ static int pick_commits(struct repository *r, if (!opts->verbose) term_clear_line(); *end_of_arg = '\0'; - res = do_exec(r, arg); + res = do_exec(r, arg, opts->quiet); *end_of_arg = saved; if (res) { @@ -5149,7 +5156,7 @@ cleanup_head_ref: hook_opt.path_to_stdin = rebase_path_rewritten_list(); strvec_push(&hook_opt.args, "rebase"); - run_hooks_opt("post-rewrite", &hook_opt); + run_hooks_opt(r, "post-rewrite", &hook_opt); } apply_autostash(rebase_path_autostash()); @@ -5489,8 +5496,10 @@ int sequencer_pick_revisions(struct repository *r, int i, res; assert(opts->revs); - if (read_and_refresh_cache(r, opts)) - return -1; + if (read_and_refresh_cache(r, opts)) { + res = -1; + goto out; + } for (i = 0; i < opts->revs->pending.nr; i++) { struct object_id oid; @@ -5505,11 +5514,14 @@ int sequencer_pick_revisions(struct repository *r, enum object_type type = oid_object_info(r, &oid, NULL); - return error(_("%s: can't cherry-pick a %s"), - name, type_name(type)); + res = error(_("%s: can't cherry-pick a %s"), + name, type_name(type)); + goto out; } - } else - return error(_("%s: bad revision"), name); + } else { + res = error(_("%s: bad revision"), name); + goto out; + } } /* @@ -5524,14 +5536,23 @@ int sequencer_pick_revisions(struct repository *r, opts->revs->no_walk && !opts->revs->cmdline.rev->flags) { struct commit *cmit; - if (prepare_revision_walk(opts->revs)) - return error(_("revision walk setup failed")); + + if (prepare_revision_walk(opts->revs)) { + res = error(_("revision walk setup failed")); + goto out; + } + cmit = get_revision(opts->revs); - if (!cmit) - return error(_("empty commit set passed")); + if (!cmit) { + res = error(_("empty commit set passed")); + goto out; + } + if (get_revision(opts->revs)) BUG("unexpected extra commit from walk"); - return single_pick(r, cmit, opts); + + res = single_pick(r, cmit, opts); + goto out; } /* @@ -5541,16 +5562,30 @@ int sequencer_pick_revisions(struct repository *r, */ if (walk_revs_populate_todo(&todo_list, opts) || - create_seq_dir(r) < 0) - return -1; - if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT)) - return error(_("can't revert as initial commit")); - if (save_head(oid_to_hex(&oid))) - return -1; - if (save_opts(opts)) - return -1; + create_seq_dir(r) < 0) { + res = -1; + goto out; + } + + if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT)) { + res = error(_("can't revert as initial commit")); + goto out; + } + + if (save_head(oid_to_hex(&oid))) { + res = -1; + goto out; + } + + if (save_opts(opts)) { + res = -1; + goto out; + } + update_abort_safety_file(); res = pick_commits(r, &todo_list, opts); + +out: todo_list_release(&todo_list); return res; } @@ -5789,7 +5824,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO; int skipped_commit = 0; struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT; - struct strbuf label = STRBUF_INIT; + struct strbuf label_from_message = STRBUF_INIT; struct commit_list *commits = NULL, **tail = &commits, *iter; struct commit_list *tips = NULL, **tips_tail = &tips; struct commit *commit; @@ -5812,6 +5847,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, oidmap_init(&state.commit2label, 0); hashmap_init(&state.labels, labels_cmp, NULL, 0); strbuf_init(&state.buf, 32); + load_branch_decorations(); if (revs->cmdline.nr && (revs->cmdline.rev[0].flags & BOTTOM)) { struct labels_entry *onto_label_entry; @@ -5872,18 +5908,18 @@ static int make_script_with_merges(struct pretty_print_context *pp, continue; } - /* Create a label */ - strbuf_reset(&label); + /* Create a label from the commit message */ + strbuf_reset(&label_from_message); if (skip_prefix(oneline.buf, "Merge ", &p1) && (p1 = strchr(p1, '\'')) && (p2 = strchr(++p1, '\''))) - strbuf_add(&label, p1, p2 - p1); + strbuf_add(&label_from_message, p1, p2 - p1); else if (skip_prefix(oneline.buf, "Merge pull request ", &p1) && (p1 = strstr(p1, " from "))) - strbuf_addstr(&label, p1 + strlen(" from ")); + strbuf_addstr(&label_from_message, p1 + strlen(" from ")); else - strbuf_addbuf(&label, &oneline); + strbuf_addbuf(&label_from_message, &oneline); strbuf_reset(&buf); strbuf_addf(&buf, "%s -C %s", @@ -5891,6 +5927,14 @@ static int make_script_with_merges(struct pretty_print_context *pp, /* label the tips of merged branches */ for (; to_merge; to_merge = to_merge->next) { + const char *label = label_from_message.buf; + const struct name_decoration *decoration = + get_name_decoration(&to_merge->item->object); + + if (decoration) + skip_prefix(decoration->name, "refs/heads/", + &label); + oid = &to_merge->item->object.oid; strbuf_addch(&buf, ' '); @@ -5903,7 +5947,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, tips_tail = &commit_list_insert(to_merge->item, tips_tail)->next; - strbuf_addstr(&buf, label_oid(oid, label.buf, &state)); + strbuf_addstr(&buf, label_oid(oid, label, &state)); } strbuf_addf(&buf, " # %s", oneline.buf); @@ -6011,7 +6055,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, free_commit_list(commits); free_commit_list(tips); - strbuf_release(&label); + strbuf_release(&label_from_message); strbuf_release(&oneline); strbuf_release(&buf); @@ -6343,8 +6387,9 @@ static int add_decorations_to_list(const struct commit *commit, /* If the branch is checked out, then leave a comment instead. */ if ((path = branch_checked_out(decoration->name))) { item->command = TODO_COMMENT; - strbuf_addf(ctx->buf, "# Ref %s checked out at '%s'\n", - decoration->name, path); + strbuf_commented_addf(ctx->buf, comment_line_str, + "Ref %s checked out at '%s'\n", + decoration->name, path); } else { struct string_list_item *sti; item->command = TODO_UPDATE_REF; @@ -6373,14 +6418,6 @@ static int add_decorations_to_list(const struct commit *commit, static int todo_list_add_update_ref_commands(struct todo_list *todo_list) { int i, res; - static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP; - static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP; - static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP; - struct decoration_filter decoration_filter = { - .include_ref_pattern = &decorate_refs_include, - .exclude_ref_pattern = &decorate_refs_exclude, - .exclude_ref_config_pattern = &decorate_refs_exclude_config, - }; struct todo_add_branch_context ctx = { .buf = &todo_list->buf, .refs_to_oids = STRING_LIST_INIT_DUP, @@ -6389,8 +6426,7 @@ static int todo_list_add_update_ref_commands(struct todo_list *todo_list) ctx.items_alloc = 2 * todo_list->nr + 1; ALLOC_ARRAY(ctx.items, ctx.items_alloc); - string_list_append(&decorate_refs_include, "refs/heads/"); - load_ref_decorations(&decoration_filter, 0); + load_branch_decorations(); for (i = 0; i < todo_list->nr; ) { struct todo_item *item = &todo_list->items[i]; @@ -323,7 +323,7 @@ static int process_request(void) die("no command requested"); if (client_hash_algo != hash_algo_by_ptr(the_repository->hash_algo)) - die("mismatched object format: server %s; client %s\n", + die("mismatched object format: server %s; client %s", the_repository->hash_algo->name, hash_algos[client_hash_algo].name); diff --git a/server-info.c b/server-info.c index f61296a60d..c5af4cd98a 100644 --- a/server-info.c +++ b/server-info.c @@ -2,7 +2,6 @@ #include "git-compat-util.h" #include "dir.h" -#include "environment.h" #include "hex.h" #include "repository.h" #include "refs.h" @@ -147,7 +146,7 @@ out: return ret; } -static int add_info_ref(const char *path, const struct object_id *oid, +static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -342,7 +341,8 @@ static int write_pack_info_file(struct update_info_ctx *uic) static int update_info_packs(int force) { - char *infofile = mkpathdup("%s/info/packs", get_object_directory()); + char *infofile = mkpathdup("%s/info/packs", + repo_get_object_directory(the_repository)); int ret; init_pack_info(infofile, force); @@ -7,16 +7,22 @@ #include "exec-cmd.h" #include "gettext.h" #include "hex.h" +#include "object-file.h" #include "object-name.h" #include "refs.h" +#include "replace-object.h" #include "repository.h" #include "config.h" #include "dir.h" #include "setup.h" +#include "shallow.h" #include "string-list.h" +#include "strvec.h" #include "chdir-notify.h" #include "path.h" #include "quote.h" +#include "tmp-objdir.h" +#include "trace.h" #include "trace2.h" #include "worktree.h" #include "exec-cmd.h" @@ -51,7 +57,7 @@ static int abspath_part_inside_repo(char *path) size_t wtlen; char *path0; int off; - const char *work_tree = precompose_string_if_needed(get_git_work_tree()); + const char *work_tree = precompose_string_if_needed(repo_get_work_tree(the_repository)); struct strbuf realpath = STRBUF_INIT; if (!work_tree) @@ -147,9 +153,9 @@ char *prefix_path(const char *prefix, int len, const char *path) { char *r = prefix_path_gently(prefix, len, NULL, path); if (!r) { - const char *hint_path = get_git_work_tree(); + const char *hint_path = repo_get_work_tree(the_repository); if (!hint_path) - hint_path = get_git_dir(); + hint_path = repo_get_git_dir(the_repository); die(_("'%s' is outside repository at '%s'"), path, absolute_path(hint_path)); } @@ -468,14 +474,14 @@ int is_nonbare_repository_dir(struct strbuf *path) int is_inside_git_dir(void) { if (inside_git_dir < 0) - inside_git_dir = is_inside_dir(get_git_dir()); + inside_git_dir = is_inside_dir(repo_get_git_dir(the_repository)); return inside_git_dir; } int is_inside_work_tree(void) { if (inside_work_tree < 0) - inside_work_tree = is_inside_dir(get_git_work_tree()); + inside_work_tree = is_inside_dir(repo_get_work_tree(the_repository)); return inside_work_tree; } @@ -490,7 +496,7 @@ void setup_work_tree(void) if (work_tree_config_is_bogus) die(_("unable to set up work tree using invalid config")); - work_tree = get_git_work_tree(); + work_tree = repo_get_work_tree(the_repository); if (!work_tree || chdir_notify(work_tree)) die(_("this operation must be run in a work tree")); @@ -518,7 +524,7 @@ static void setup_original_cwd(void) * directory we inherited from our parent process, which is a * directory we want to avoid removing. * - * For convience, we would like to have the path relative to the + * For convenience, we would like to have the path relative to the * worktree instead of an absolute path. * * Yes, startup_info->original_cwd is usually the same as 'prefix', @@ -547,7 +553,7 @@ static void setup_original_cwd(void) * Get our worktree; we only protect the current working directory * if it's in the worktree. */ - worktree = get_git_work_tree(); + worktree = repo_get_work_tree(the_repository); if (!worktree) goto no_prevention_needed; @@ -677,6 +683,9 @@ static enum extension_result handle_extension(const char *var, "extensions.refstorage", value); data->ref_storage_format = format; return EXTENSION_OK; + } else if (!strcmp(ext, "relativeworktrees")) { + data->relative_worktrees = git_config_bool(var, value); + return EXTENSION_OK; } return EXTENSION_UNKNOWN; } @@ -1062,9 +1071,9 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, set_git_work_tree("."); /* set_git_work_tree() must have been called by now */ - worktree = get_git_work_tree(); + worktree = repo_get_work_tree(the_repository); - /* both get_git_work_tree() and cwd are already normalized */ + /* both repo_get_work_tree() and cwd are already normalized */ if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */ set_git_dir(gitdirenv, 0); free(gitfile); @@ -1215,7 +1224,7 @@ static int canonicalize_ceiling_entry(struct string_list_item *item, } struct safe_directory_data { - const char *path; + char *path; int is_safe; }; @@ -1235,17 +1244,45 @@ static int safe_directory_cb(const char *key, const char *value, char *allowed = NULL; if (!git_config_pathname(&allowed, key, value)) { - const char *check = allowed ? allowed : value; - if (ends_with(check, "/*")) { - size_t len = strlen(check); - if (!fspathncmp(check, data->path, len - 1)) + char *normalized = NULL; + + /* + * Setting safe.directory to a non-absolute path + * makes little sense---it won't be relative to + * the configuration file the item is defined in. + * Except for ".", which means "if we are at the top + * level of a repository, then it is OK", which is + * slightly tighter than "*" that allows discovery. + */ + if (!is_absolute_path(allowed) && strcmp(allowed, ".")) { + warning(_("safe.directory '%s' not absolute"), + allowed); + goto next; + } + + /* + * A .gitconfig in $HOME may be shared across + * different machines and safe.directory entries + * may or may not exist as paths on all of these + * machines. In other words, it is not a warning + * worthy event when there is no such path on this + * machine---the entry may be useful elsewhere. + */ + normalized = real_pathdup(allowed, 0); + if (!normalized) + goto next; + + if (ends_with(normalized, "/*")) { + size_t len = strlen(normalized); + if (!fspathncmp(normalized, data->path, len - 1)) data->is_safe = 1; - } else if (!fspathcmp(data->path, check)) { + } else if (!fspathcmp(data->path, normalized)) { data->is_safe = 1; } - } - if (allowed != value) + next: + free(normalized); free(allowed); + } } return 0; @@ -1263,9 +1300,7 @@ static int ensure_valid_ownership(const char *gitfile, const char *worktree, const char *gitdir, struct strbuf *report) { - struct safe_directory_data data = { - .path = worktree ? worktree : gitdir - }; + struct safe_directory_data data = { 0 }; if (!git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0) && (!gitfile || is_path_owned_by_current_user(gitfile, report)) && @@ -1274,12 +1309,22 @@ static int ensure_valid_ownership(const char *gitfile, return 1; /* + * normalize the data.path for comparison with normalized paths + * that come from the configuration file. The path is unsafe + * if it cannot be normalized. + */ + data.path = real_pathdup(worktree ? worktree : gitdir, 0); + if (!data.path) + return 0; + + /* * data.path is the "path" that identifies the repository and it is * constant regardless of what failed above. data.is_safe should be * initialized to false, and might be changed by the callback. */ git_protected_config(safe_directory_cb, &data); + free(data.path); return data.is_safe; } @@ -1577,6 +1622,106 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir, return result; } +void setup_git_env(const char *git_dir) +{ + char *git_replace_ref_base; + const char *shallow_file; + const char *replace_ref_base; + struct set_gitdir_args args = { NULL }; + struct strvec to_free = STRVEC_INIT; + + args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT); + args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT); + args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT); + args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT); + args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT); + if (getenv(GIT_QUARANTINE_ENVIRONMENT)) { + args.disable_ref_updates = 1; + } + + repo_set_gitdir(the_repository, git_dir, &args); + strvec_clear(&to_free); + + if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) + disable_replace_refs(); + replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT); + git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base + : "refs/replace/"); + update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base); + + shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); + if (shallow_file) + set_alternate_shallow_file(the_repository, shallow_file, 0); + + if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0)) + fetch_if_missing = 0; +} + +static void set_git_dir_1(const char *path) +{ + xsetenv(GIT_DIR_ENVIRONMENT, path, 1); + setup_git_env(path); +} + +static void update_relative_gitdir(const char *name UNUSED, + const char *old_cwd, + const char *new_cwd, + void *data UNUSED) +{ + char *path = reparent_relative_path(old_cwd, new_cwd, + repo_get_git_dir(the_repository)); + struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb(); + + trace_printf_key(&trace_setup_key, + "setup: move $GIT_DIR to '%s'", + path); + set_git_dir_1(path); + if (tmp_objdir) + tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd); + free(path); +} + +void set_git_dir(const char *path, int make_realpath) +{ + struct strbuf realpath = STRBUF_INIT; + + if (make_realpath) { + strbuf_realpath(&realpath, path, 1); + path = realpath.buf; + } + + set_git_dir_1(path); + if (!is_absolute_path(path)) + chdir_notify_register(NULL, update_relative_gitdir, NULL); + + strbuf_release(&realpath); +} + +static int git_work_tree_initialized; + +/* + * Note. This works only before you used a work tree. This was added + * primarily to support git-clone to work in a new repository it just + * created, and is not meant to flip between different work trees. + */ +void set_git_work_tree(const char *new_work_tree) +{ + if (git_work_tree_initialized) { + struct strbuf realpath = STRBUF_INIT; + + strbuf_realpath(&realpath, new_work_tree, 1); + new_work_tree = realpath.buf; + if (strcmp(new_work_tree, the_repository->worktree)) + die("internal error: work tree has already been set\n" + "Current worktree: %s\nNew worktree: %s", + the_repository->worktree, new_work_tree); + strbuf_release(&realpath); + return; + } + git_work_tree_initialized = 1; + repo_set_worktree(the_repository, new_work_tree); +} + const char *setup_git_directory_gently(int *nongit_ok) { static struct strbuf cwd = STRBUF_INIT; @@ -1712,6 +1857,8 @@ const char *setup_git_directory_gently(int *nongit_ok) repo_fmt.ref_storage_format); the_repository->repository_format_worktree_config = repo_fmt.worktree_config; + the_repository->repository_format_relative_worktrees = + repo_fmt.relative_worktrees; /* take ownership of repo_fmt.partial_clone */ the_repository->repository_format_partial_clone = repo_fmt.partial_clone; @@ -1800,7 +1947,7 @@ void check_repository_format(struct repository_format *fmt) struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; if (!fmt) fmt = &repo_fmt; - check_repository_format_gently(get_git_dir(), fmt, NULL); + check_repository_format_gently(repo_get_git_dir(the_repository), fmt, NULL); startup_info->have_repository = 1; repo_set_hash_algo(the_repository, fmt->hash_algo); repo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo); @@ -1808,6 +1955,8 @@ void check_repository_format(struct repository_format *fmt) fmt->ref_storage_format); the_repository->repository_format_worktree_config = fmt->worktree_config; + the_repository->repository_format_relative_worktrees = + fmt->relative_worktrees; the_repository->repository_format_partial_clone = xstrdup_or_null(fmt->partial_clone); clear_repository_format(&repo_fmt); @@ -1871,7 +2020,7 @@ struct template_dir_cb_data { }; static int template_dir_cb(const char *key, const char *value, - const struct config_context *ctx, void *d) + const struct config_context *ctx UNUSED, void *d) { struct template_dir_cb_data *data = d; @@ -2032,7 +2181,7 @@ static void copy_templates(const char *option_template) goto close_free_return; } - strbuf_addstr(&path, get_git_common_dir()); + strbuf_addstr(&path, repo_get_common_dir(the_repository)); strbuf_complete(&path, '/'); copy_templates_1(&path, &template_path, dir); close_free_return: @@ -2062,8 +2211,8 @@ void initialize_repository_version(int hash_algo, enum ref_storage_format ref_storage_format, int reinit) { - char repo_version_string[10]; - int repo_version = GIT_REPO_VERSION; + struct strbuf repo_version = STRBUF_INIT; + int target_version = GIT_REPO_VERSION; /* * Note that we initialize the repository version to 1 when the ref @@ -2074,12 +2223,7 @@ void initialize_repository_version(int hash_algo, */ if (hash_algo != GIT_HASH_SHA1 || ref_storage_format != REF_STORAGE_FORMAT_FILES) - repo_version = GIT_REPO_VERSION_READ; - - /* This forces creation of new config file */ - xsnprintf(repo_version_string, sizeof(repo_version_string), - "%d", repo_version); - git_config_set("core.repositoryformatversion", repo_version_string); + target_version = GIT_REPO_VERSION_READ; if (hash_algo != GIT_HASH_SHA1 && hash_algo != GIT_HASH_UNKNOWN) git_config_set("extensions.objectformat", @@ -2092,6 +2236,25 @@ void initialize_repository_version(int hash_algo, ref_storage_format_to_name(ref_storage_format)); else if (reinit) git_config_set_gently("extensions.refstorage", NULL); + + if (reinit) { + struct strbuf config = STRBUF_INIT; + struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; + + strbuf_git_common_path(&config, the_repository, "config"); + read_repository_format(&repo_fmt, config.buf); + + if (repo_fmt.v1_only_extensions.nr) + target_version = GIT_REPO_VERSION_READ; + + strbuf_release(&config); + clear_repository_format(&repo_fmt); + } + + strbuf_addf(&repo_version, "%d", target_version); + git_config_set("core.repositoryformatversion", repo_version.buf); + + strbuf_release(&repo_version); } static int is_reinit(void) @@ -2156,7 +2319,7 @@ static int create_default_files(const char *template_path, char *path; int reinit; int filemode; - const char *work_tree = get_git_work_tree(); + const char *work_tree = repo_get_work_tree(the_repository); /* * First copy the templates -- we might have the default @@ -2188,10 +2351,10 @@ static int create_default_files(const char *template_path, * shared-repository settings, we would need to fix them up. */ if (get_shared_repository()) { - adjust_shared_perm(get_git_dir()); + adjust_shared_perm(repo_get_git_dir(the_repository)); } - initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0); + initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit); /* Check filemode trustability */ path = git_path_buf(&buf, "config"); @@ -2212,7 +2375,7 @@ static int create_default_files(const char *template_path, else { git_config_set("core.bare", "false"); /* allow template config file to override the default */ - if (log_all_ref_updates == LOG_REFS_UNSET) + if (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET) git_config_set("core.logallrefupdates", "true"); if (needs_work_tree_config(original_git_dir, work_tree)) git_config_set("core.worktree", work_tree); @@ -2246,7 +2409,7 @@ static void create_object_directory(void) struct strbuf path = STRBUF_INIT; size_t baselen; - strbuf_addstr(&path, get_object_directory()); + strbuf_addstr(&path, repo_get_object_directory(the_repository)); baselen = path.len; safe_create_dir(path.buf, 1); @@ -2278,20 +2441,73 @@ static void separate_git_dir(const char *git_dir, const char *git_link) if (rename(src, git_dir)) die_errno(_("unable to move %s to %s"), src, git_dir); - repair_worktrees(NULL, NULL); + repair_worktrees_after_gitdir_move(src); } write_file(git_link, "gitdir: %s", git_dir); } -static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash) +struct default_format_config { + int hash; + enum ref_storage_format ref_format; +}; + +static int read_default_format_config(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *payload) +{ + struct default_format_config *cfg = payload; + char *str = NULL; + int ret; + + if (!strcmp(key, "init.defaultobjectformat")) { + ret = git_config_string(&str, key, value); + if (ret) + goto out; + cfg->hash = hash_algo_by_name(str); + if (cfg->hash == GIT_HASH_UNKNOWN) + warning(_("unknown hash algorithm '%s'"), str); + goto out; + } + + if (!strcmp(key, "init.defaultrefformat")) { + ret = git_config_string(&str, key, value); + if (ret) + goto out; + cfg->ref_format = ref_storage_format_by_name(str); + if (cfg->ref_format == REF_STORAGE_FORMAT_UNKNOWN) + warning(_("unknown ref storage format '%s'"), str); + goto out; + } + + ret = 0; +out: + free(str); + return ret; +} + +static void repository_format_configure(struct repository_format *repo_fmt, + int hash, enum ref_storage_format ref_format) { - const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT); + struct default_format_config cfg = { + .hash = GIT_HASH_UNKNOWN, + .ref_format = REF_STORAGE_FORMAT_UNKNOWN, + }; + struct config_options opts = { + .respect_includes = 1, + .ignore_repo = 1, + .ignore_worktree = 1, + }; + const char *env; + + config_with_options(read_default_format_config, &cfg, NULL, NULL, &opts); + /* * If we already have an initialized repo, don't allow the user to * specify a different algorithm, as that could cause corruption. * Otherwise, if the user has specified one on the command line, use it. */ + env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT); if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo) die(_("attempt to reinitialize repository with different hash")); else if (hash != GIT_HASH_UNKNOWN) @@ -2301,26 +2517,27 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash if (env_algo == GIT_HASH_UNKNOWN) die(_("unknown hash algorithm '%s'"), env); repo_fmt->hash_algo = env_algo; + } else if (cfg.hash != GIT_HASH_UNKNOWN) { + repo_fmt->hash_algo = cfg.hash; } -} - -static void validate_ref_storage_format(struct repository_format *repo_fmt, - enum ref_storage_format format) -{ - const char *name = getenv("GIT_DEFAULT_REF_FORMAT"); + repo_set_hash_algo(the_repository, repo_fmt->hash_algo); + env = getenv("GIT_DEFAULT_REF_FORMAT"); if (repo_fmt->version >= 0 && - format != REF_STORAGE_FORMAT_UNKNOWN && - format != repo_fmt->ref_storage_format) { + ref_format != REF_STORAGE_FORMAT_UNKNOWN && + ref_format != repo_fmt->ref_storage_format) { die(_("attempt to reinitialize repository with different reference storage format")); - } else if (format != REF_STORAGE_FORMAT_UNKNOWN) { - repo_fmt->ref_storage_format = format; - } else if (name) { - format = ref_storage_format_by_name(name); - if (format == REF_STORAGE_FORMAT_UNKNOWN) - die(_("unknown ref storage format '%s'"), name); - repo_fmt->ref_storage_format = format; + } else if (ref_format != REF_STORAGE_FORMAT_UNKNOWN) { + repo_fmt->ref_storage_format = ref_format; + } else if (env) { + ref_format = ref_storage_format_by_name(env); + if (ref_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), env); + repo_fmt->ref_storage_format = ref_format; + } else if (cfg.ref_format != REF_STORAGE_FORMAT_UNKNOWN) { + repo_fmt->ref_storage_format = cfg.ref_format; } + repo_set_ref_storage_format(the_repository, repo_fmt->ref_storage_format); } int init_db(const char *git_dir, const char *real_git_dir, @@ -2344,31 +2561,24 @@ int init_db(const char *git_dir, const char *real_git_dir, die(_("%s already exists"), real_git_dir); set_git_dir(real_git_dir, 1); - git_dir = get_git_dir(); + git_dir = repo_get_git_dir(the_repository); separate_git_dir(git_dir, original_git_dir); } else { set_git_dir(git_dir, 1); - git_dir = get_git_dir(); + git_dir = repo_get_git_dir(the_repository); } startup_info->have_repository = 1; - /* Check to see if the repository version is right. + /* + * Check to see if the repository version is right. * Note that a newly created repository does not have * config file, so this will not fail. What we are catching * is an attempt to reinitialize new repository with an old tool. */ check_repository_format(&repo_fmt); - validate_hash_algorithm(&repo_fmt, hash); - validate_ref_storage_format(&repo_fmt, ref_storage_format); - - /* - * Now that we have set up both the hash algorithm and the ref storage - * format we can update the repository's settings accordingly. - */ - repo_set_hash_algo(the_repository, repo_fmt.hash_algo); - repo_set_ref_storage_format(the_repository, repo_fmt.ref_storage_format); + repository_format_configure(&repo_fmt, hash, ref_storage_format); /* * Ensure `core.hidedotfiles` is processed. This must happen after we @@ -94,6 +94,9 @@ static inline int discover_git_directory(struct strbuf *commondir, return 0; } +void set_git_dir(const char *path, int make_realpath); +void set_git_work_tree(const char *tree); + const char *setup_git_directory_gently(int *); const char *setup_git_directory(void); char *prefix_path(const char *prefix, int len, const char *path); @@ -126,6 +129,7 @@ struct repository_format { int precious_objects; char *partial_clone; /* value of extensions.partialclone */ int worktree_config; + int relative_worktrees; int is_bare; int hash_algo; int compat_hash_algo; @@ -176,7 +180,7 @@ int verify_repository_format(const struct repository_format *format, struct strbuf *err); /* - * Check the repository format version in the path found in get_git_dir(), + * Check the repository format version in the path found in repo_get_git_dir(the_repository), * and die if it is a version we don't understand. Generally one would * set_git_dir() before calling this, and use it only for "are we in a valid * repo?". diff --git a/sha1/openssl.h b/sha1/openssl.h index 006c1f4ba5..1038af47da 100644 --- a/sha1/openssl.h +++ b/sha1/openssl.h @@ -40,10 +40,12 @@ static inline void openssl_SHA1_Clone(struct openssl_SHA1_CTX *dst, EVP_MD_CTX_copy_ex(dst->ectx, src->ectx); } +#ifndef platform_SHA_CTX #define platform_SHA_CTX openssl_SHA1_CTX #define platform_SHA1_Init openssl_SHA1_Init #define platform_SHA1_Clone openssl_SHA1_Clone #define platform_SHA1_Update openssl_SHA1_Update #define platform_SHA1_Final openssl_SHA1_Final +#endif #endif /* SHA1_OPENSSL_H */ diff --git a/sha1dc_git.h b/sha1dc_git.h index 60e3ce8439..f6f880cabe 100644 --- a/sha1dc_git.h +++ b/sha1dc_git.h @@ -18,7 +18,10 @@ void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *); void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len); #define platform_SHA_IS_SHA1DC /* used by "test-tool sha1-is-sha1dc" */ + +#ifndef platform_SHA_CTX #define platform_SHA_CTX SHA1_CTX #define platform_SHA1_Init git_SHA1DCInit #define platform_SHA1_Update git_SHA1DCUpdate #define platform_SHA1_Final git_SHA1DCFinal +#endif @@ -51,6 +51,7 @@ int unregister_shallow(const struct object_id *oid) int pos = commit_graft_pos(the_repository, oid); if (pos < 0) return -1; + free(the_repository->parsed_objects->grafts[pos]); if (pos + 1 < the_repository->parsed_objects->grafts_nr) MOVE_ARRAY(the_repository->parsed_objects->grafts + pos, the_repository->parsed_objects->grafts + pos + 1, @@ -97,7 +98,7 @@ static void reset_repository_shallow(struct repository *r) { r->parsed_objects->is_shallow = -1; stat_validity_clear(r->parsed_objects->shallow_stat); - reset_commit_grafts(r); + parsed_object_pool_reset_commit_grafts(r->parsed_objects); } int commit_shallow_file(struct repository *r, struct shallow_lock *lk) @@ -487,6 +488,15 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa) void clear_shallow_info(struct shallow_info *info) { + if (info->used_shallow) { + for (size_t i = 0; i < info->shallow->nr; i++) + free(info->used_shallow[i]); + free(info->used_shallow); + } + + free(info->need_reachability_test); + free(info->reachable); + free(info->shallow_ref); free(info->ours); free(info->theirs); } @@ -612,6 +622,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid, } static int mark_uninteresting(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data UNUSED) @@ -727,6 +738,7 @@ struct commit_array { }; static int add_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) @@ -143,6 +143,7 @@ static void run_shell(void) } free(argv); + free(split_args); free(rawargs); } while (!done); } @@ -216,9 +217,8 @@ int cmd_main(int argc, const char **argv) count = split_cmdline(prog, &user_argv); if (count >= 0) { if (is_valid_cmd_name(user_argv[0])) { - prog = make_cmd(user_argv[0]); - user_argv[0] = prog; - execv(user_argv[0], (char *const *) user_argv); + char *cmd = make_cmd(user_argv[0]); + execv(cmd, (char *const *) user_argv); } free(prog); free(user_argv); diff --git a/sideband.c b/sideband.c index 5d8907151f..02805573fa 100644 --- a/sideband.c +++ b/sideband.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "color.h" #include "config.h" @@ -30,28 +32,27 @@ static int use_sideband_colors(void) const char *key = "color.remote"; struct strbuf sb = STRBUF_INIT; - char *value; + const char *value; int i; if (use_sideband_colors_cached >= 0) return use_sideband_colors_cached; - if (!git_config_get_string(key, &value)) { + if (!git_config_get_string_tmp(key, &value)) use_sideband_colors_cached = git_config_colorbool(key, value); - } else if (!git_config_get_string("color.ui", &value)) { + else if (!git_config_get_string_tmp("color.ui", &value)) use_sideband_colors_cached = git_config_colorbool("color.ui", value); - } else { + else use_sideband_colors_cached = GIT_COLOR_AUTO; - } for (i = 0; i < ARRAY_SIZE(keywords); i++) { strbuf_reset(&sb); strbuf_addf(&sb, "%s.%s", key, keywords[i].keyword); - if (git_config_get_string(sb.buf, &value)) - continue; - if (color_parse(value, keywords[i].color)) + if (git_config_get_string_tmp(sb.buf, &value)) continue; + color_parse(value, keywords[i].color); } + strbuf_release(&sb); return use_sideband_colors_cached; } @@ -190,7 +191,7 @@ int demultiplex_sideband(const char *me, int status, int linelen = brk - b; /* - * For message accross packet boundary, there would have + * For message across packet boundary, there would have * a nonempty "scratch" buffer from last call of this * function, and there may have a leading CR/LF in "buf". * For this case we should add a clear-to-eol suffix to diff --git a/simple-ipc.h b/simple-ipc.h index a849d9f841..3916eaf70d 100644 --- a/simple-ipc.h +++ b/simple-ipc.h @@ -179,11 +179,20 @@ struct ipc_server_opts * When a client IPC message is received, the `application_cb` will be * called (possibly on a random thread) to handle the message and * optionally compose a reply message. + * + * This initializes all threads but no actual work will be done until + * ipc_server_start_async() is called. + */ +int ipc_server_init_async(struct ipc_server_data **returned_server_data, + const char *path, const struct ipc_server_opts *opts, + ipc_server_application_cb *application_cb, + void *application_data); + +/* + * Let an async server start running. This needs to be called only once + * after initialization. */ -int ipc_server_run_async(struct ipc_server_data **returned_server_data, - const char *path, const struct ipc_server_opts *opts, - ipc_server_application_cb *application_cb, - void *application_data); +void ipc_server_start_async(struct ipc_server_data *server_data); /* * Gently signal the IPC server pool to shutdown. No new client diff --git a/sparse-index.c b/sparse-index.c index 9958656ded..2107840bfc 100644 --- a/sparse-index.c +++ b/sparse-index.c @@ -1,5 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "environment.h" +#include "ewah/ewok.h" #include "gettext.h" #include "name-hash.h" #include "read-cache-ll.h" @@ -19,9 +22,10 @@ * advice for advice.sparseIndexExpanded when expanding a sparse index to a full * one. However, this is sometimes done on purpose, such as in the sparse-checkout * builtin, even when index.sparse=false. This may be disabled in - * convert_to_sparse(). + * convert_to_sparse() or by commands that know they will lead to a full + * expansion, but this message is not actionable. */ -static int give_advice_on_expansion = 1; +int give_advice_on_expansion = 1; #define ADVICE_MSG \ "The sparse index is expanding to a full index, a slow operation.\n" \ "Your working directory likely has contents that are outside of\n" \ @@ -239,7 +243,8 @@ int convert_to_sparse(struct index_state *istate, int flags) cache_tree_update(istate, 0); istate->fsmonitor_has_run_once = 0; - FREE_AND_NULL(istate->fsmonitor_dirty); + ewah_free(istate->fsmonitor_dirty); + istate->fsmonitor_dirty = NULL; FREE_AND_NULL(istate->fsmonitor_last_update); istate->sparse_index = INDEX_COLLAPSED; @@ -435,7 +440,8 @@ void expand_index(struct index_state *istate, struct pattern_list *pl) istate->cache_nr = full->cache_nr; istate->cache_alloc = full->cache_alloc; istate->fsmonitor_has_run_once = 0; - FREE_AND_NULL(istate->fsmonitor_dirty); + ewah_free(istate->fsmonitor_dirty); + istate->fsmonitor_dirty = NULL; FREE_AND_NULL(istate->fsmonitor_last_update); strbuf_release(&base); diff --git a/sparse-index.h b/sparse-index.h index a16f3e67d7..727034be7c 100644 --- a/sparse-index.h +++ b/sparse-index.h @@ -1,6 +1,13 @@ #ifndef SPARSE_INDEX_H__ #define SPARSE_INDEX_H__ +/* + * If performing an operation where the index is supposed to expand to a + * full index, then disable the advice message by setting this global to + * zero. + */ +extern int give_advice_on_expansion; + struct index_state; #define SPARSE_INDEX_MEMORY_ONLY (1 << 0) int is_sparse_index_allowed(struct index_state *istate, int flags); diff --git a/split-index.c b/split-index.c index 120c8190b1..cfbc773e6c 100644 --- a/split-index.c +++ b/split-index.c @@ -97,7 +97,11 @@ void move_cache_to_base_index(struct index_state *istate) mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool); } - ALLOC_ARRAY(si->base, 1); + if (si->base) + release_index(si->base); + else + ALLOC_ARRAY(si->base, 1); + index_state_init(si->base, istate->repo); si->base->version = istate->version; /* zero timestamp disables racy test in ce_write_index() */ diff --git a/statinfo.c b/statinfo.c index 3c6bc049c1..30a164b0e6 100644 --- a/statinfo.c +++ b/statinfo.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "environment.h" #include "statinfo.h" @@ -637,28 +637,6 @@ static inline void strbuf_complete_line(struct strbuf *sb) strbuf_complete(sb, '\n'); } -/* - * Copy "name" to "sb", expanding any special @-marks as handled by - * repo_interpret_branch_name(). The result is a non-qualified branch name - * (so "foo" or "origin/master" instead of "refs/heads/foo" or - * "refs/remotes/origin/master"). - * - * Note that the resulting name may not be a syntactically valid refname. - * - * If "allowed" is non-zero, restrict the set of allowed expansions. See - * repo_interpret_branch_name() for details. - */ -void strbuf_branchname(struct strbuf *sb, const char *name, - unsigned allowed); - -/* - * Like strbuf_branchname() above, but confirm that the result is - * syntactically valid to be used as a local branch name in refs/heads/. - * - * The return value is "0" if the result is valid, and "-1" otherwise. - */ -int strbuf_check_branch_ref(struct strbuf *sb, const char *name); - typedef int (*char_predicate)(char ch); void strbuf_addstr_urlencode(struct strbuf *sb, const char *name, @@ -56,6 +56,28 @@ void strvec_pushv(struct strvec *array, const char **items) strvec_push(array, *items); } +void strvec_splice(struct strvec *array, size_t idx, size_t len, + const char **replacement, size_t replacement_len) +{ + if (idx + len > array->nr) + BUG("range outside of array boundary"); + if (replacement_len > len) { + if (array->v == empty_strvec) + array->v = NULL; + ALLOC_GROW(array->v, array->nr + (replacement_len - len) + 1, + array->alloc); + array->v[array->nr + (replacement_len - len)] = NULL; + } + for (size_t i = 0; i < len; i++) + free((char *)array->v[idx + i]); + if ((replacement_len != len) && array->nr) + memmove(array->v + idx + replacement_len, array->v + idx + len, + (array->nr - idx - len + 1) * sizeof(char *)); + array->nr += replacement_len - len; + for (size_t i = 0; i < replacement_len; i++) + array->v[idx + i] = xstrdup(replacement[i]); +} + const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement) { char *to_free; @@ -67,6 +67,15 @@ void strvec_pushl(struct strvec *, ...); /* Push a null-terminated array of strings onto the end of the array. */ void strvec_pushv(struct strvec *, const char **); +/* + * Replace `len` values starting at `idx` with the provided replacement + * strings. If `len` is zero this is effectively an insert at the given `idx`. + * If `replacement_len` is zero this is effectively a delete of `len` items + * starting at `idx`. + */ +void strvec_splice(struct strvec *array, size_t idx, size_t len, + const char **replacement, size_t replacement_len); + /** * Replace the value at the given index with a new value. The index must be * valid. Returns a pointer to the inserted value. diff --git a/submodule-config.c b/submodule-config.c index 9b0bb0b9f4..9c8c37b259 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -95,7 +95,7 @@ static void free_one_config(struct submodule_entry *entry) free((void *) entry->config->branch); free((void *) entry->config->url); free((void *) entry->config->ignore); - free((void *) entry->config->update_strategy.command); + submodule_update_strategy_release(&entry->config->update_strategy); free(entry->config); } @@ -899,27 +899,26 @@ static void traverse_tree_submodules(struct repository *r, { struct tree_desc tree; struct submodule_tree_entry *st_entry; - struct name_entry *name_entry; + struct name_entry name_entry; char *tree_path = NULL; + char *tree_buf; - name_entry = xmalloc(sizeof(*name_entry)); - - fill_tree_descriptor(r, &tree, treeish_name); - while (tree_entry(&tree, name_entry)) { + tree_buf = fill_tree_descriptor(r, &tree, treeish_name); + while (tree_entry(&tree, &name_entry)) { if (prefix) tree_path = - mkpathdup("%s/%s", prefix, name_entry->path); + mkpathdup("%s/%s", prefix, name_entry.path); else - tree_path = xstrdup(name_entry->path); + tree_path = xstrdup(name_entry.path); - if (S_ISGITLINK(name_entry->mode) && + if (S_ISGITLINK(name_entry.mode) && is_tree_submodule_active(r, root_tree, tree_path)) { ALLOC_GROW(out->entries, out->entry_nr + 1, out->entry_alloc); st_entry = &out->entries[out->entry_nr++]; st_entry->name_entry = xmalloc(sizeof(*st_entry->name_entry)); - *st_entry->name_entry = *name_entry; + *st_entry->name_entry = name_entry; st_entry->submodule = submodule_from_path(r, root_tree, tree_path); st_entry->repo = xmalloc(sizeof(*st_entry->repo)); @@ -927,11 +926,13 @@ static void traverse_tree_submodules(struct repository *r, root_tree)) FREE_AND_NULL(st_entry->repo); - } else if (S_ISDIR(name_entry->mode)) + } else if (S_ISDIR(name_entry.mode)) traverse_tree_submodules(r, root_tree, tree_path, - &name_entry->oid, out); + &name_entry.oid, out); free(tree_path); } + + free(tree_buf); } void submodules_of_tree(struct repository *r, @@ -945,6 +946,16 @@ void submodules_of_tree(struct repository *r, traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out); } +void submodule_entry_list_release(struct submodule_entry_list *list) +{ + for (size_t i = 0; i < list->entry_nr; i++) { + free(list->entries[i].name_entry); + repo_clear(list->entries[i].repo); + free(list->entries[i].repo); + } + free(list->entries); +} + void submodule_free(struct repository *r) { if (r->submodule_cache) diff --git a/submodule-config.h b/submodule-config.h index b6133af71b..f55d4e3b61 100644 --- a/submodule-config.h +++ b/submodule-config.h @@ -136,4 +136,7 @@ struct submodule_entry_list { void submodules_of_tree(struct repository *r, const struct object_id *treeish_name, struct submodule_entry_list *ret); + +void submodule_entry_list_release(struct submodule_entry_list *list); + #endif /* SUBMODULE_CONFIG_H */ diff --git a/submodule.c b/submodule.c index ab99a30253..7ec564854d 100644 --- a/submodule.c +++ b/submodule.c @@ -159,7 +159,7 @@ int remove_path_from_gitmodules(const char *path) } strbuf_addstr(§, "submodule."); strbuf_addstr(§, submodule->name); - if (git_config_rename_section_in_file(GITMODULES_FILE, sect.buf, NULL) < 0) { + if (repo_config_rename_section_in_file(the_repository, GITMODULES_FILE, sect.buf, NULL) < 0) { /* Maybe the user already did that, don't error out here */ warning(_("Could not remove .gitmodules entry for %s"), path); strbuf_release(§); @@ -175,11 +175,11 @@ void stage_updated_gitmodules(struct index_state *istate) die(_("staging updated .gitmodules failed")); } -static struct string_list added_submodule_odb_paths = STRING_LIST_INIT_NODUP; +static struct string_list added_submodule_odb_paths = STRING_LIST_INIT_DUP; void add_submodule_odb_by_path(const char *path) { - string_list_insert(&added_submodule_odb_paths, xstrdup(path)); + string_list_insert(&added_submodule_odb_paths, path); } int register_all_submodule_odb_as_alternates(void) @@ -424,6 +424,11 @@ int parse_submodule_update_strategy(const char *value, return 0; } +void submodule_update_strategy_release(struct submodule_update_strategy *strategy) +{ + free((char *) strategy->command); +} + const char *submodule_update_type_to_string(enum submodule_update_type type) { switch (type) { @@ -953,6 +958,7 @@ static void free_submodules_data(struct string_list *submodules) } static int has_remote(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data UNUSED) { @@ -1168,8 +1174,8 @@ static int push_submodule(const char *path, if (remote->origin != REMOTE_UNCONFIGURED) { int i; strvec_push(&cp.args, remote->name); - for (i = 0; i < rs->raw_nr; i++) - strvec_push(&cp.args, rs->raw[i]); + for (i = 0; i < rs->nr; i++) + strvec_push(&cp.args, rs->items[i].raw); } prepare_submodule_repo_env(&cp.env); @@ -1203,8 +1209,8 @@ static void submodule_push_check(const char *path, const char *head, strvec_push(&cp.args, head); strvec_push(&cp.args, remote->name); - for (i = 0; i < rs->raw_nr; i++) - strvec_push(&cp.args, rs->raw[i]); + for (i = 0; i < rs->nr; i++) + strvec_push(&cp.args, rs->items[i].raw); prepare_submodule_repo_env(&cp.env); cp.git_cmd = 1; @@ -1273,6 +1279,7 @@ int push_unpushed_submodules(struct repository *r, } static int append_oid_to_array(const char *ref UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *data) { @@ -1496,7 +1503,7 @@ static const struct submodule *get_non_gitmodules_submodule(const char *path) return (const struct submodule *) ret; } -static void fetch_task_release(struct fetch_task *p) +static void fetch_task_free(struct fetch_task *p) { if (p->free_sub) free((void*)p->sub); @@ -1508,6 +1515,7 @@ static void fetch_task_release(struct fetch_task *p) FREE_AND_NULL(p->repo); strvec_clear(&p->git_args); + free(p); } static struct repository *get_submodule_repo_for(struct repository *r, @@ -1576,8 +1584,7 @@ static struct fetch_task *fetch_task_create(struct submodule_parallel_fetch *spf return task; cleanup: - fetch_task_release(task); - free(task); + fetch_task_free(task); return NULL; } @@ -1607,8 +1614,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf, } else { struct strbuf empty_submodule_path = STRBUF_INIT; - fetch_task_release(task); - free(task); + fetch_task_free(task); /* * An empty directory is normal, @@ -1654,8 +1660,7 @@ get_fetch_task_from_changed(struct submodule_parallel_fetch *spf, cs_data->path, repo_find_unique_abbrev(the_repository, cs_data->super_oid, DEFAULT_ABBREV)); - fetch_task_release(task); - free(task); + fetch_task_free(task); continue; } @@ -1763,7 +1768,7 @@ static int fetch_start_failure(struct strbuf *err UNUSED, spf->result = 1; - fetch_task_release(task); + fetch_task_free(task); return 0; } @@ -1828,8 +1833,7 @@ static int fetch_finish(int retvalue, struct strbuf *err UNUSED, } out: - fetch_task_release(task); - + fetch_task_free(task); return 0; } @@ -1883,6 +1887,9 @@ int fetch_submodules(struct repository *r, strvec_clear(&spf.args); out: free_submodules_data(&spf.changed_submodule_names); + string_list_clear(&spf.seen_submodule_names, 0); + strbuf_release(&spf.submodules_with_errors); + free(spf.oid_fetch_tasks); return spf.result; } @@ -2462,7 +2469,7 @@ void absorb_git_dir_into_superproject(const char *path, } else { /* Is it already absorbed into the superprojects git dir? */ char *real_sub_git_dir = real_pathdup(sub_git_dir, 1); - char *real_common_git_dir = real_pathdup(get_git_common_dir(), 1); + char *real_common_git_dir = real_pathdup(repo_get_common_dir(the_repository), 1); if (!starts_with(real_sub_git_dir, real_common_git_dir)) relocate_single_git_dir_into_superproject(path, super_prefix); diff --git a/submodule.h b/submodule.h index b50d29eba4..4deb1b5f84 100644 --- a/submodule.h +++ b/submodule.h @@ -41,6 +41,10 @@ struct submodule_update_strategy { .type = SM_UPDATE_UNSPECIFIED, \ } +int parse_submodule_update_strategy(const char *value, + struct submodule_update_strategy *dst); +void submodule_update_strategy_release(struct submodule_update_strategy *strategy); + int is_gitmodules_unmerged(struct index_state *istate); int is_writing_gitmodules_ok(void); int is_staging_gitmodules_ok(struct index_state *istate); @@ -70,8 +74,6 @@ void die_in_unpopulated_submodule(struct index_state *istate, void die_path_inside_submodule(struct index_state *istate, const struct pathspec *ps); enum submodule_update_type parse_submodule_update_type(const char *value); -int parse_submodule_update_strategy(const char *value, - struct submodule_update_strategy *dst); const char *submodule_update_type_to_string(enum submodule_update_type type); void handle_ignore_submodules_arg(struct diff_options *, const char *); void show_submodule_diff_summary(struct diff_options *o, const char *path, diff --git a/t/Makefile b/t/Makefile index 4c30e7c06f..131ffd778f 100644 --- a/t/Makefile +++ b/t/Makefile @@ -48,6 +48,7 @@ CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.tes CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c) UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES)) +UNIT_TEST_PROGRAMS += unit-tests/bin/unit-tests$(X) UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS)) UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS)) @@ -68,7 +69,8 @@ failed: test -z "$$failed" || $(MAKE) $$failed prove: pre-clean check-chainlint $(TEST_LINT) - @echo "*** prove (shell & unit tests) ***"; $(CHAINLINTSUPPRESS) TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) :: $(GIT_TEST_OPTS) + @echo "*** prove (shell & unit tests) ***" + @$(CHAINLINTSUPPRESS) TEST_OPTIONS='$(GIT_TEST_OPTS)' TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) $(MAKE) clean-except-prove-cache $(T): @@ -368,24 +368,6 @@ excluded as so much relies on it, but this might change in the future. GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole test suite. Accept any boolean values that are accepted by git-config. -GIT_TEST_PASSING_SANITIZE_LEAK=true skips those tests that haven't -declared themselves as leak-free by setting -"TEST_PASSES_SANITIZE_LEAK=true" before sourcing "test-lib.sh". This -test mode is used by the "linux-leaks" CI target. - -GIT_TEST_PASSING_SANITIZE_LEAK=check checks that our -"TEST_PASSES_SANITIZE_LEAK=true" markings are current. Rather than -skipping those tests that haven't set "TEST_PASSES_SANITIZE_LEAK=true" -before sourcing "test-lib.sh" this mode runs them with -"--invert-exit-code". This is used to check that there's a one-to-one -mapping between "TEST_PASSES_SANITIZE_LEAK=true" and those tests that -pass under "SANITIZE=leak". This is especially useful when testing a -series that fixes various memory leaks with "git rebase -x". - -GIT_TEST_PASSING_SANITIZE_LEAK=check when combined with "--immediate" -will run to completion faster, and result in the same failing -tests. - GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version' default to n. @@ -445,9 +427,9 @@ GIT_TEST_MULTI_PACK_INDEX=<boolean>, when true, forces the multi-pack- index to be written after every 'git repack' command, and overrides the 'core.multiPackIndex' setting to true. -GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=<boolean>, when true, sets the -'--bitmap' option on all invocations of 'git multi-pack-index write', -and ignores pack-objects' '--write-bitmap-index'. +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=<boolean>, when true, sets +the '--incremental' option on all invocations of 'git multi-pack-index +write'. GIT_TEST_SIDEBAND_ALL=<boolean>, when true, overrides the 'uploadpack.allowSidebandAll' setting to true, and when false, forces @@ -462,8 +444,9 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to use in the test scripts. Recognized values for <hash-algo> are "sha1" and "sha256". -GIT_TEST_DEFAULT_REF_FORMAT=<format> specifies which ref storage format -to use in the test scripts. Recognized values for <format> are "files". +GIT_TEST_DEFAULT_REF_FORMAT=<format> specifies which ref storage format to use +in the test scripts. Recognized values for <format> are "files" and +"reftable". GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the 'pack.writeReverseIndex' setting. diff --git a/t/chainlint.pl b/t/chainlint.pl index 5361f23b1d..f0598e3934 100755 --- a/t/chainlint.pl +++ b/t/chainlint.pl @@ -9,9 +9,9 @@ # Input arguments are pathnames of shell scripts containing test definitions, # or globs referencing a collection of scripts. For each problem discovered, # the pathname of the script containing the test is printed along with the test -# name and the test body with a `?!FOO?!` annotation at the location of each -# detected problem, where "FOO" is a tag such as "AMP" which indicates a broken -# &&-chain. Returns zero if no problems are discovered, otherwise non-zero. +# name and the test body with a `?!LINT: ...?!` annotation at the location of +# each detected problem, where "..." is an explanation of the problem. Returns +# zero if no problems are discovered, otherwise non-zero. use warnings; use strict; @@ -181,7 +181,7 @@ sub swallow_heredocs { $self->{lineno} += () = $body =~ /\n/sg; next; } - push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]); + push(@{$self->{parser}->{problems}}, ['HEREDOC', $tag]); $$b =~ /(?:\G|\n).*\z/gc; # consume rest of input my $body = substr($$b, $start, pos($$b) - $start); $self->{lineno} += () = $body =~ /\n/sg; @@ -238,6 +238,7 @@ sub new { stop => [], output => [], heredocs => {}, + insubshell => 0, } => $class; $self->{lexer} = Lexer->new($self, $s); return $self; @@ -296,8 +297,11 @@ sub parse_group { sub parse_subshell { my $self = shift @_; - return ($self->parse(qr/^\)$/), - $self->expect(')')); + $self->{insubshell}++; + my @tokens = ($self->parse(qr/^\)$/), + $self->expect(')')); + $self->{insubshell}--; + return @tokens; } sub parse_case_pattern { @@ -528,7 +532,7 @@ sub parse_loop_body { return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]); # flag missing "return/exit" handling explicit failure in loop body my $n = find_non_nl(\@tokens); - push(@{$self->{problems}}, ['LOOP', $tokens[$n]]); + push(@{$self->{problems}}, [$self->{insubshell} ? 'LOOPEXIT' : 'LOOPRETURN', $tokens[$n]]); return @tokens; } @@ -587,6 +591,7 @@ sub new { my $class = shift @_; my $self = $class->SUPER::new(@_); $self->{ntests} = 0; + $self->{nerrs} = 0; return $self; } @@ -619,6 +624,15 @@ sub unwrap { return $s } +sub format_problem { + local $_ = shift; + /^AMP$/ && return "missing '&&'"; + /^LOOPRETURN$/ && return "missing '|| return 1'"; + /^LOOPEXIT$/ && return "missing '|| exit 1'"; + /^HEREDOC$/ && return 'unclosed heredoc'; + die("unrecognized problem type '$_'\n"); +} + sub check_test { my $self = shift @_; my $title = unwrap(shift @_); @@ -634,22 +648,26 @@ sub check_test { my $parser = TestParser->new(\$body); my @tokens = $parser->parse(); my $problems = $parser->{problems}; + $self->{nerrs} += @$problems; return unless $emit_all || @$problems; my $c = main::fd_colors(1); + my ($erropen, $errclose) = -t 1 ? ("$c->{rev}$c->{red}", $c->{reset}) : ('?!', '?!'); my $start = 0; my $checked = ''; for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) { my ($label, $token) = @$_; my $pos = $token->[2]; - $checked .= substr($body, $start, $pos - $start) . " ?!$label?! "; + my $err = format_problem($label); + $checked .= substr($body, $start, $pos - $start); + $checked .= ' ' unless $checked =~ /\s$/; + $checked .= "${erropen}LINT: $err$errclose"; + $checked .= ' ' unless $pos >= length($body) || + substr($body, $pos, 1) =~ /^\s/; $start = $pos; } $checked .= substr($body, $start); $checked =~ s/^/$lineno++ . ' '/mge; $checked =~ s/^\d+ \n//; - $checked =~ s/(\s) \?!/$1?!/mg; - $checked =~ s/\?! (\s)/?!$1/mg; - $checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg; $checked =~ s/^\d+/$c->{dim}$&$c->{reset}/mg; $checked .= "\n" unless $checked =~ /\n$/; push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked"); @@ -791,9 +809,9 @@ sub check_script { my $c = fd_colors(1); my $s = join('', @{$parser->{output}}); $emit->("$c->{bold}$c->{blue}# chainlint: $path$c->{reset}\n" . $s); - $nerrs += () = $s =~ /\?![^?]+\?!/g; } $ntests += $parser->{ntests}; + $nerrs += $parser->{nerrs}; } return [$id, $nscripts, $ntests, $nerrs]; } diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect index 338ecd5861..5677e16cad 100644 --- a/t/chainlint/arithmetic-expansion.expect +++ b/t/chainlint/arithmetic-expansion.expect @@ -4,6 +4,6 @@ 5 baz 6 ) && 7 ( -8 bar=$((42 + 1)) ?!AMP?! +8 bar=$((42 + 1)) ?!LINT: missing '&&'?! 9 baz 10 ) diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect index b62e3d58c3..3d3f854c0d 100644 --- a/t/chainlint/block.expect +++ b/t/chainlint/block.expect @@ -1,20 +1,20 @@ 2 ( 3 foo && 4 { -5 echo a ?!AMP?! +5 echo a ?!LINT: missing '&&'?! 6 echo b 7 } && 8 bar && 9 { 10 echo c -11 } ?!AMP?! +11 } ?!LINT: missing '&&'?! 12 baz 13 ) && 14 15 { -16 echo a; ?!AMP?! echo b +16 echo a; ?!LINT: missing '&&'?! echo b 17 } && -18 { echo a; ?!AMP?! echo b; } && +18 { echo a; ?!LINT: missing '&&'?! echo b; } && 19 20 { 21 echo "${var}9" && diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect index 9a1838736f..b7b1ce8509 100644 --- a/t/chainlint/broken-chain.expect +++ b/t/chainlint/broken-chain.expect @@ -1,6 +1,6 @@ 2 ( 3 foo && -4 bar ?!AMP?! +4 bar ?!LINT: missing '&&'?! 5 baz && 6 wop 7 ) diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect index c04c61ff36..0a3b09e470 100644 --- a/t/chainlint/case.expect +++ b/t/chainlint/case.expect @@ -9,11 +9,11 @@ 10 case "$x" in 11 x) foo ;; 12 *) bar ;; -13 esac ?!AMP?! +13 esac ?!LINT: missing '&&'?! 14 foobar 15 ) && 16 ( 17 case "$x" in 1) true;; esac && -18 case "$y" in 2) false;; esac ?!AMP?! +18 case "$y" in 2) false;; esac ?!LINT: missing '&&'?! 19 foobar 20 ) diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect index 4f815f8e14..f6a0a301e9 100644 --- a/t/chainlint/chain-break-false.expect +++ b/t/chainlint/chain-break-false.expect @@ -4,6 +4,6 @@ 5 echo failed! 6 false 7 else -8 echo it went okay ?!AMP?! +8 echo it went okay ?!LINT: missing '&&'?! 9 congratulate user 10 fi diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect index a546b714a6..f2501bba90 100644 --- a/t/chainlint/chained-block.expect +++ b/t/chainlint/chained-block.expect @@ -1,5 +1,5 @@ 2 echo nobody home && { -3 test the doohicky ?!AMP?! +3 test the doohicky ?!LINT: missing '&&'?! 4 right now 5 } && 6 diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect index f78b268291..93fb1a6578 100644 --- a/t/chainlint/chained-subshell.expect +++ b/t/chainlint/chained-subshell.expect @@ -1,10 +1,10 @@ 2 mkdir sub && ( 3 cd sub && -4 foo the bar ?!AMP?! +4 foo the bar ?!LINT: missing '&&'?! 5 nuff said 6 ) && 7 8 cut "-d " -f actual | (read s1 s2 s3 && -9 test -f $s1 ?!AMP?! +9 test -f $s1 ?!LINT: missing '&&'?! 10 test $(cat $s2) = tree2path1 && 11 test $(cat $s3) = tree3path1) diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect index 5e31b36db6..73809fd585 100644 --- a/t/chainlint/command-substitution.expect +++ b/t/chainlint/command-substitution.expect @@ -4,6 +4,6 @@ 5 baz 6 ) && 7 ( -8 bar=$(gobble blocks) ?!AMP?! +8 bar=$(gobble blocks) ?!LINT: missing '&&'?! 9 baz 10 ) diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect index 3a740103db..e66bb2d5d0 100644 --- a/t/chainlint/complex-if-in-cuddled-loop.expect +++ b/t/chainlint/complex-if-in-cuddled-loop.expect @@ -4,6 +4,6 @@ 5 : 6 else 7 echo >file -8 fi ?!LOOP?! +8 fi ?!LINT: missing '|| exit 1'?! 9 done) && 10 test ! -f file diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect index b06d638311..1864b3fc8b 100644 --- a/t/chainlint/cuddled.expect +++ b/t/chainlint/cuddled.expect @@ -2,7 +2,7 @@ 3 bar 4 ) && 5 -6 (cd foo ?!AMP?! +6 (cd foo ?!LINT: missing '&&'?! 7 bar 8 ) && 9 @@ -13,5 +13,5 @@ 14 (cd foo && 15 bar) && 16 -17 (cd foo ?!AMP?! +17 (cd foo ?!LINT: missing '&&'?! 18 bar) diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect index 908aeedf96..5029eacce3 100644 --- a/t/chainlint/for-loop.expect +++ b/t/chainlint/for-loop.expect @@ -1,14 +1,14 @@ 2 ( 3 for i in a b c 4 do -5 echo $i ?!AMP?! -6 cat <<-\EOF ?!LOOP?! +5 echo $i ?!LINT: missing '&&'?! +6 cat <<-\EOF ?!LINT: missing '|| exit 1'?! 7 bar 8 EOF -9 done ?!AMP?! +9 done ?!LINT: missing '&&'?! 10 11 for i in a b c; do 12 echo $i && -13 cat $i ?!LOOP?! +13 cat $i ?!LINT: missing '|| exit 1'?! 14 done 15 ) diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect index c226246b25..9e46a3554a 100644 --- a/t/chainlint/function.expect +++ b/t/chainlint/function.expect @@ -4,8 +4,8 @@ 5 6 remove_object() { 7 file=$(sha1_file "$*") && -8 test -e "$file" ?!AMP?! +8 test -e "$file" ?!LINT: missing '&&'?! 9 rm -f "$file" -10 } ?!AMP?! +10 } ?!LINT: missing '&&'?! 11 12 sha1_file arg && remove_object arg diff --git a/t/chainlint/here-doc-body-indent.expect b/t/chainlint/here-doc-body-indent.expect index 4323acc93d..4306faee86 100644 --- a/t/chainlint/here-doc-body-indent.expect +++ b/t/chainlint/here-doc-body-indent.expect @@ -1,2 +1,2 @@ -2 echo "we should find this" ?!AMP?! +2 echo "we should find this" ?!LINT: missing '&&'?! 3 echo "even though our heredoc has its indent stripped" diff --git a/t/chainlint/here-doc-body-pathological.expect b/t/chainlint/here-doc-body-pathological.expect index a93a1fa3aa..2f8ea03a47 100644 --- a/t/chainlint/here-doc-body-pathological.expect +++ b/t/chainlint/here-doc-body-pathological.expect @@ -1,7 +1,7 @@ -2 echo "outer here-doc does not allow indented end-tag" ?!AMP?! +2 echo "outer here-doc does not allow indented end-tag" ?!LINT: missing '&&'?! 3 cat >file <<-\EOF && 4 but this inner here-doc 5 does allow indented EOF 6 EOF -7 echo "missing chain after" ?!AMP?! +7 echo "missing chain after" ?!LINT: missing '&&'?! 8 echo "but this line is OK because it's the end" diff --git a/t/chainlint/here-doc-body.expect b/t/chainlint/here-doc-body.expect index ddf1c412af..df8d79bc0a 100644 --- a/t/chainlint/here-doc-body.expect +++ b/t/chainlint/here-doc-body.expect @@ -1,7 +1,7 @@ -2 echo "missing chain before" ?!AMP?! +2 echo "missing chain before" ?!LINT: missing '&&'?! 3 cat >file <<-\EOF && 4 inside inner here-doc 5 these are not shell commands 6 EOF -7 echo "missing chain after" ?!AMP?! +7 echo "missing chain after" ?!LINT: missing '&&'?! 8 echo "but this line is OK because it's the end" diff --git a/t/chainlint/here-doc-double.expect b/t/chainlint/here-doc-double.expect index 20dba4b452..e5e981889f 100644 --- a/t/chainlint/here-doc-double.expect +++ b/t/chainlint/here-doc-double.expect @@ -1,2 +1,2 @@ -8 echo "actual test commands" ?!AMP?! +8 echo "actual test commands" ?!LINT: missing '&&'?! 9 echo "that should be checked" diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect index 277a11202d..ec0e61505b 100644 --- a/t/chainlint/here-doc-indent-operator.expect +++ b/t/chainlint/here-doc-indent-operator.expect @@ -4,7 +4,7 @@ 5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data 6 EOF 7 -8 cat >expect << -EOF ?!AMP?! +8 cat >expect << -EOF ?!LINT: missing '&&'?! 9 this is not indented 10 -EOF 11 diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect index 41b55f6437..8128f15b92 100644 --- a/t/chainlint/here-doc-multi-line-command-subst.expect +++ b/t/chainlint/here-doc-multi-line-command-subst.expect @@ -3,6 +3,6 @@ 4 fossil 5 vegetable 6 END -7 wiffle) ?!AMP?! +7 wiffle) ?!LINT: missing '&&'?! 8 echo $x 9 ) diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect index c71828589e..a03a04ff3d 100644 --- a/t/chainlint/here-doc-multi-line-string.expect +++ b/t/chainlint/here-doc-multi-line-string.expect @@ -1,6 +1,6 @@ 2 ( 3 cat <<-\TXT && echo "multi-line -4 string" ?!AMP?! +4 string" ?!LINT: missing '&&'?! 5 fizzle 6 TXT 7 bap diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect index 9daf3d294a..6d2a03dfdb 100644 --- a/t/chainlint/if-condition-split.expect +++ b/t/chainlint/if-condition-split.expect @@ -2,6 +2,6 @@ 3 marcia || 4 kevin 5 then -6 echo "nomads" ?!AMP?! +6 echo "nomads" ?!LINT: missing '&&'?! 7 echo "for sure" 8 fi diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect index ff8c60dbdb..7e3ba740de 100644 --- a/t/chainlint/if-in-loop.expect +++ b/t/chainlint/if-in-loop.expect @@ -5,8 +5,8 @@ 6 then 7 echo "err" 8 exit 1 -9 fi ?!AMP?! +9 fi ?!LINT: missing '&&'?! 10 foo -11 done ?!AMP?! +11 done ?!LINT: missing '&&'?! 12 bar 13 ) diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect index 965d7e41a2..924caa2e4e 100644 --- a/t/chainlint/if-then-else.expect +++ b/t/chainlint/if-then-else.expect @@ -1,7 +1,7 @@ 2 ( 3 if test -n "" 4 then -5 echo very ?!AMP?! +5 echo very ?!LINT: missing '&&'?! 6 echo empty 7 elif test -z "" 8 then @@ -11,7 +11,7 @@ 12 cat <<-\EOF 13 bar 14 EOF -15 fi ?!AMP?! +15 fi ?!LINT: missing '&&'?! 16 echo poodle 17 ) && 18 ( diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect index 0285c0b22c..4b4080124e 100644 --- a/t/chainlint/inline-comment.expect +++ b/t/chainlint/inline-comment.expect @@ -1,6 +1,6 @@ 2 ( 3 foobar && # comment 1 -4 barfoo ?!AMP?! # wrong position for && +4 barfoo ?!LINT: missing '&&'?! # wrong position for && 5 flibble "not a # comment" 6 ) && 7 diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect index 40c06f0d53..7d846b878d 100644 --- a/t/chainlint/loop-detect-failure.expect +++ b/t/chainlint/loop-detect-failure.expect @@ -11,5 +11,5 @@ 12 do 13 printf "%"$n"s" X > r2/large.$n && 14 git -C r2 add large.$n && -15 git -C r2 commit -m "$n" ?!LOOP?! +15 git -C r2 commit -m "$n" ?!LINT: missing '|| return 1'?! 16 done diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect index 4e8c67c914..32e076ad1b 100644 --- a/t/chainlint/loop-in-if.expect +++ b/t/chainlint/loop-in-if.expect @@ -3,10 +3,10 @@ 4 then 5 while true 6 do -7 echo "pop" ?!AMP?! -8 echo "glup" ?!LOOP?! -9 done ?!AMP?! +7 echo "pop" ?!LINT: missing '&&'?! +8 echo "glup" ?!LINT: missing '|| exit 1'?! +9 done ?!LINT: missing '&&'?! 10 foo -11 fi ?!AMP?! +11 fi ?!LINT: missing '&&'?! 12 bar 13 ) diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect index 62c54e3a5e..9d33297525 100644 --- a/t/chainlint/multi-line-string.expect +++ b/t/chainlint/multi-line-string.expect @@ -3,7 +3,7 @@ 4 line 2 5 line 3" && 6 y="line 1 -7 line2" ?!AMP?! +7 line2" ?!LINT: missing '&&'?! 8 foobar 9 ) && 10 ( diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect index a6ce52a1da..0a6f3c29b2 100644 --- a/t/chainlint/negated-one-liner.expect +++ b/t/chainlint/negated-one-liner.expect @@ -1,5 +1,5 @@ 2 ! (foo && bar) && 3 ! (foo && bar) >baz && 4 -5 ! (foo; ?!AMP?! bar) && -6 ! (foo; ?!AMP?! bar) >baz +5 ! (foo; ?!LINT: missing '&&'?! bar) && +6 ! (foo; ?!LINT: missing '&&'?! bar) >baz diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect index 0191c9c294..fec2c74274 100644 --- a/t/chainlint/nested-cuddled-subshell.expect +++ b/t/chainlint/nested-cuddled-subshell.expect @@ -5,7 +5,7 @@ 6 7 (cd foo && 8 bar -9 ) ?!AMP?! +9 ) ?!LINT: missing '&&'?! 10 11 ( 12 cd foo && @@ -13,13 +13,13 @@ 14 15 ( 16 cd foo && -17 bar) ?!AMP?! +17 bar) ?!LINT: missing '&&'?! 18 19 (cd foo && 20 bar) && 21 22 (cd foo && -23 bar) ?!AMP?! +23 bar) ?!LINT: missing '&&'?! 24 25 foobar 26 ) diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect index 70d9b68dc9..571f4c9514 100644 --- a/t/chainlint/nested-here-doc.expect +++ b/t/chainlint/nested-here-doc.expect @@ -18,7 +18,7 @@ 19 toink 20 INPUT_END 21 -22 cat <<-\EOT ?!AMP?! +22 cat <<-\EOT ?!LINT: missing '&&'?! 23 text goes here 24 data <<EOF 25 data goes here diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect index c13c4d2f90..b4aaa621a2 100644 --- a/t/chainlint/nested-loop-detect-failure.expect +++ b/t/chainlint/nested-loop-detect-failure.expect @@ -2,8 +2,8 @@ 3 do 4 for j in 0 1 2 3 4 5 6 7 8 9; 5 do -6 echo "$i$j" >"path$i$j" ?!LOOP?! -7 done ?!LOOP?! +6 echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?! +7 done ?!LINT: missing '|| return 1'?! 8 done && 9 10 for i in 0 1 2 3 4 5 6 7 8 9; @@ -18,7 +18,7 @@ 19 do 20 for j in 0 1 2 3 4 5 6 7 8 9; 21 do -22 echo "$i$j" >"path$i$j" ?!LOOP?! +22 echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?! 23 done || return 1 24 done && 25 diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect index f89a8d03a8..078c6f275f 100644 --- a/t/chainlint/nested-subshell-comment.expect +++ b/t/chainlint/nested-subshell-comment.expect @@ -6,6 +6,6 @@ 7 # minor numbers of cows (or do they?) 8 baz && 9 snaff -10 ) ?!AMP?! +10 ) ?!LINT: missing '&&'?! 11 fuzzy 12 ) diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect index 811e8a7912..a8d85d5d5b 100644 --- a/t/chainlint/nested-subshell.expect +++ b/t/chainlint/nested-subshell.expect @@ -7,7 +7,7 @@ 8 9 cd foo && 10 ( -11 echo a ?!AMP?! +11 echo a ?!LINT: missing '&&'?! 12 echo b 13 ) >file 14 ) diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect index 611b7b75cb..5d51705a7a 100644 --- a/t/chainlint/not-heredoc.expect +++ b/t/chainlint/not-heredoc.expect @@ -9,6 +9,6 @@ 10 echo ourside && 11 echo "=======" && 12 echo theirside && -13 echo ">>>>>>> theirs" ?!AMP?! +13 echo ">>>>>>> theirs" ?!LINT: missing '&&'?! 14 poodle 15 ) >merged diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect index 49dcf065ef..e1fcbd3639 100644 --- a/t/chainlint/one-liner-for-loop.expect +++ b/t/chainlint/one-liner-for-loop.expect @@ -3,7 +3,7 @@ 4 cd dir-rename-and-content && 5 test_write_lines 1 2 3 4 5 >foo && 6 mkdir olddir && -7 for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?! +7 for i in a b c; do echo $i >olddir/$i; ?!LINT: missing '|| exit 1'?! done ?!LINT: missing '&&'?! 8 git add foo olddir && 9 git commit -m "original" && 10 ) diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect index 9861811283..5deeb05070 100644 --- a/t/chainlint/one-liner.expect +++ b/t/chainlint/one-liner.expect @@ -2,8 +2,8 @@ 3 (foo && bar) | 4 (foo && bar) >baz && 5 -6 (foo; ?!AMP?! bar) && -7 (foo; ?!AMP?! bar) | -8 (foo; ?!AMP?! bar) >baz && +6 (foo; ?!LINT: missing '&&'?! bar) && +7 (foo; ?!LINT: missing '&&'?! bar) | +8 (foo; ?!LINT: missing '&&'?! bar) >baz && 9 10 (foo "bar; baz") diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect index 1bbe5a2ce1..d947c76584 100644 --- a/t/chainlint/pipe.expect +++ b/t/chainlint/pipe.expect @@ -4,7 +4,7 @@ 5 baz && 6 7 fish | -8 cow ?!AMP?! +8 cow ?!LINT: missing '&&'?! 9 10 sunder 11 ) diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect index 866438310c..2b499fbe70 100644 --- a/t/chainlint/semicolon.expect +++ b/t/chainlint/semicolon.expect @@ -1,19 +1,19 @@ 2 ( -3 cat foo ; ?!AMP?! echo bar ?!AMP?! -4 cat foo ; ?!AMP?! echo bar +3 cat foo ; ?!LINT: missing '&&'?! echo bar ?!LINT: missing '&&'?! +4 cat foo ; ?!LINT: missing '&&'?! echo bar 5 ) && 6 ( -7 cat foo ; ?!AMP?! echo bar && -8 cat foo ; ?!AMP?! echo bar +7 cat foo ; ?!LINT: missing '&&'?! echo bar && +8 cat foo ; ?!LINT: missing '&&'?! echo bar 9 ) && 10 ( 11 echo "foo; bar" && -12 cat foo; ?!AMP?! echo bar +12 cat foo; ?!LINT: missing '&&'?! echo bar 13 ) && 14 ( 15 foo; 16 ) && 17 (cd foo && 18 for i in a b c; do -19 echo; ?!LOOP?! +19 echo; ?!LINT: missing '|| exit 1'?! 20 done) diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect index 5647500c82..e450caf948 100644 --- a/t/chainlint/subshell-here-doc.expect +++ b/t/chainlint/subshell-here-doc.expect @@ -6,7 +6,7 @@ 7 nevermore... 8 EOF 9 -10 cat <<EOF >bip ?!AMP?! +10 cat <<EOF >bip ?!LINT: missing '&&'?! 11 fish fly high 12 EOF 13 diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect index 214316c6a0..265d996a21 100644 --- a/t/chainlint/subshell-one-liner.expect +++ b/t/chainlint/subshell-one-liner.expect @@ -3,17 +3,17 @@ 4 (foo && bar) | 5 (foo && bar) >baz && 6 -7 (foo; ?!AMP?! bar) && -8 (foo; ?!AMP?! bar) | -9 (foo; ?!AMP?! bar) >baz && +7 (foo; ?!LINT: missing '&&'?! bar) && +8 (foo; ?!LINT: missing '&&'?! bar) | +9 (foo; ?!LINT: missing '&&'?! bar) >baz && 10 11 (foo || exit 1) && 12 (foo || exit 1) | 13 (foo || exit 1) >baz && 14 -15 (foo && bar) ?!AMP?! +15 (foo && bar) ?!LINT: missing '&&'?! 16 -17 (foo && bar; ?!AMP?! baz) ?!AMP?! +17 (foo && bar; ?!LINT: missing '&&'?! baz) ?!LINT: missing '&&'?! 18 19 foobar 20 ) diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect index 64f3235d26..387189b6de 100644 --- a/t/chainlint/token-pasting.expect +++ b/t/chainlint/token-pasting.expect @@ -2,13 +2,13 @@ 3 git config filter.rot13.clean ./rot13.sh && 4 5 { -6 echo "*.t filter=rot13" ?!AMP?! +6 echo "*.t filter=rot13" ?!LINT: missing '&&'?! 7 echo "*.i ident" 8 } >.gitattributes && 9 10 { -11 echo a b c d e f g h i j k l m ?!AMP?! -12 echo n o p q r s t u v w x y z ?!AMP?! +11 echo a b c d e f g h i j k l m ?!LINT: missing '&&'?! +12 echo n o p q r s t u v w x y z ?!LINT: missing '&&'?! 13 echo '$Id$' 14 } >test && 15 cat test >test.t && @@ -19,7 +19,7 @@ 20 git checkout -- test test.t test.i && 21 22 echo "content-test2" >test2.o && -23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?! +23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!LINT: missing '&&'?! 24 25 downstream_url_for_sed=$( 26 printf "%sn" "$downstream_url" | diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect index f78e23cb63..156906c85a 100644 --- a/t/chainlint/unclosed-here-doc-indent.expect +++ b/t/chainlint/unclosed-here-doc-indent.expect @@ -1,4 +1,4 @@ 2 command_which_is_run && -3 cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! && +3 cat >expect <<-\EOF ?!LINT: unclosed heredoc?! && 4 we forget to end the here-doc 5 command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect index 51304672cf..752c608862 100644 --- a/t/chainlint/unclosed-here-doc.expect +++ b/t/chainlint/unclosed-here-doc.expect @@ -1,5 +1,5 @@ 2 command_which_is_run && -3 cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! && +3 cat >expect <<\EOF ?!LINT: unclosed heredoc?! && 4 we try to end the here-doc below, 5 but the indentation throws us off 6 since the operator is not "<<-". diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect index 5ffabd5a93..2ba5582165 100644 --- a/t/chainlint/while-loop.expect +++ b/t/chainlint/while-loop.expect @@ -1,14 +1,14 @@ 2 ( 3 while true 4 do -5 echo foo ?!AMP?! -6 cat <<-\EOF ?!LOOP?! +5 echo foo ?!LINT: missing '&&'?! +6 cat <<-\EOF ?!LINT: missing '|| exit 1'?! 7 bar 8 EOF -9 done ?!AMP?! +9 done ?!LINT: missing '&&'?! 10 11 while true; do 12 echo foo && -13 cat bar ?!LOOP?! +13 cat bar ?!LINT: missing '|| exit 1'?! 14 done 15 ) diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl index b2b28c2ced..6ee7700eb4 100755 --- a/t/check-non-portable-shell.pl +++ b/t/check-non-portable-shell.pl @@ -49,8 +49,8 @@ while (<>) { /\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)'; /\blocal\s+[A-Za-z0-9_]*=\$([A-Za-z0-9_{]|[(][^(])/ and err q(quote "$val" in 'local var=$val'); - /^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and - err '"FOO=bar shell_func" assignment extends beyond "shell_func"'; + /\b([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and !/test_env.+=/ and exists($func{$4}) and + err '"FOO=bar shell_func" is not portable (use test_env FOO=bar shell_func)'; $line = ''; # this resets our $. for each file close ARGV if eof; diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c index 8a3fd0009a..6967c8e25c 100644 --- a/t/helper/test-advise.c +++ b/t/helper/test-advise.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "test-tool.h" #include "advice.h" #include "config.h" diff --git a/t/helper/test-config.c b/t/helper/test-config.c index ed444ca4c2..33247f0e92 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "test-tool.h" #include "config.h" #include "setup.h" @@ -94,7 +96,8 @@ int cmd__config(int argc, const char **argv) struct config_set cs; if (argc == 3 && !strcmp(argv[1], "read_early_config")) { - read_early_config(early_config_cb, (void *)argv[2]); + read_early_config(the_repository, early_config_cb, + (void *)argv[2]); return 0; } diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c index 4f010d5324..b2e70837a9 100644 --- a/t/helper/test-dump-untracked-cache.c +++ b/t/helper/test-dump-untracked-cache.c @@ -68,5 +68,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED) printf("flags %08x\n", uc->dir_flags); if (uc->root) dump(uc->root, &base); + + strbuf_release(&base); return 0; } diff --git a/t/helper/test-example-tap.c b/t/helper/test-example-tap.c index d072ad559f..229d495ecf 100644 --- a/t/helper/test-example-tap.c +++ b/t/helper/test-example-tap.c @@ -70,8 +70,10 @@ static void t_empty(void) ; /* empty */ } -int cmd__example_tap(int argc, const char **argv) +int cmd__example_tap(int argc UNUSED, const char **argv UNUSED) { + check(1); + test_res = TEST(check_res = check_int(1, ==, 1), "passing test"); TEST(t_res(1), "passing test and assertion return 1"); test_res = TEST(check_res = check_int(1, ==, 2), "failing test"); @@ -92,5 +94,38 @@ int cmd__example_tap(int argc, const char **argv) test_res = TEST(t_empty(), "test with no checks"); TEST(check_int(test_res, ==, 0), "test with no checks returns 0"); + if_test ("if_test passing test") + check_int(1, ==, 1); + if_test ("if_test failing test") + check_int(1, ==, 2); + if_test ("if_test passing TEST_TODO()") + TEST_TODO(check(0)); + if_test ("if_test failing TEST_TODO()") + TEST_TODO(check(1)); + if_test ("if_test test_skip()") { + check(0); + test_skip("missing prerequisite"); + check(1); + } + if_test ("if_test test_skip() inside TEST_TODO()") + TEST_TODO((test_skip("missing prerequisite"), 1)); + if_test ("if_test TEST_TODO() after failing check") { + check(0); + TEST_TODO(check(0)); + } + if_test ("if_test failing check after TEST_TODO()") { + check(1); + TEST_TODO(check(0)); + check(0); + } + if_test ("if_test messages from failing string and char comparison") { + check_str("\thello\\", "there\"\n"); + check_str("NULL", NULL); + check_char('a', ==, '\n'); + check_char('\\', ==, '\''); + } + if_test ("if_test test with no checks") + ; /* nothing */ + return test_done(); } diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c index 14b2b0c12c..85a69a4e55 100644 --- a/t/helper/test-find-pack.c +++ b/t/helper/test-find-pack.c @@ -40,7 +40,7 @@ int cmd__find_pack(int argc, const char **argv) die("cannot parse %s as an object name", argv[0]); for (p = get_all_packs(the_repository); p; p = p->next) - if (find_pack_entry_one(oid.hash, p)) { + if (find_pack_entry_one(&oid, p)) { printf("%s\n", p->pack_name); actual_count++; } diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index 2912899558..7782ae585e 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -12,11 +12,6 @@ struct test_entry char key[FLEX_ARRAY]; }; -static const char *get_value(const struct test_entry *e) -{ - return e->key + strlen(e->key) + 1; -} - static int test_entry_cmp(const void *cmp_data, const struct hashmap_entry *eptr, const struct hashmap_entry *entry_or_key, @@ -141,30 +136,16 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) /* * Read stdin line by line and print result of commands to stdout: * - * hash key -> strhash(key) memhash(key) strihash(key) memihash(key) - * put key value -> NULL / old value - * get key -> NULL / value - * remove key -> NULL / old value - * iterate -> key1 value1\nkey2 value2\n... - * size -> tablesize numentries - * * perfhashmap method rounds -> test hashmap.[ch] performance */ -int cmd__hashmap(int argc, const char **argv) +int cmd__hashmap(int argc UNUSED, const char **argv UNUSED) { struct string_list parts = STRING_LIST_INIT_NODUP; struct strbuf line = STRBUF_INIT; - int icase; - struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase); - - /* init hash map */ - icase = argc > 1 && !strcmp("ignorecase", argv[1]); /* process commands from stdin */ while (strbuf_getline(&line, stdin) != EOF) { char *cmd, *p1, *p2; - unsigned int hash = 0; - struct test_entry *entry; /* break line into command and up to two parameters */ string_list_setlen(&parts, 0); @@ -180,84 +161,8 @@ int cmd__hashmap(int argc, const char **argv) cmd = parts.items[0].string; p1 = parts.nr >= 1 ? parts.items[1].string : NULL; p2 = parts.nr >= 2 ? parts.items[2].string : NULL; - if (p1) - hash = icase ? strihash(p1) : strhash(p1); - - if (!strcmp("add", cmd) && p1 && p2) { - - /* create entry with key = p1, value = p2 */ - entry = alloc_test_entry(hash, p1, p2); - - /* add to hashmap */ - hashmap_add(&map, &entry->ent); - - } else if (!strcmp("put", cmd) && p1 && p2) { - - /* create entry with key = p1, value = p2 */ - entry = alloc_test_entry(hash, p1, p2); - - /* add / replace entry */ - entry = hashmap_put_entry(&map, entry, ent); - - /* print and free replaced entry, if any */ - puts(entry ? get_value(entry) : "NULL"); - free(entry); - - } else if (!strcmp("get", cmd) && p1) { - /* lookup entry in hashmap */ - entry = hashmap_get_entry_from_hash(&map, hash, p1, - struct test_entry, ent); - - /* print result */ - if (!entry) - puts("NULL"); - hashmap_for_each_entry_from(&map, entry, ent) - puts(get_value(entry)); - - } else if (!strcmp("remove", cmd) && p1) { - - /* setup static key */ - struct hashmap_entry key; - struct hashmap_entry *rm; - hashmap_entry_init(&key, hash); - - /* remove entry from hashmap */ - rm = hashmap_remove(&map, &key, p1); - entry = rm ? container_of(rm, struct test_entry, ent) - : NULL; - - /* print result and free entry*/ - puts(entry ? get_value(entry) : "NULL"); - free(entry); - - } else if (!strcmp("iterate", cmd)) { - struct hashmap_iter iter; - - hashmap_for_each_entry(&map, &iter, entry, - ent /* member name */) - printf("%s %s\n", entry->key, get_value(entry)); - - } else if (!strcmp("size", cmd)) { - - /* print table sizes */ - printf("%u %u\n", map.tablesize, - hashmap_get_size(&map)); - - } else if (!strcmp("intern", cmd) && p1) { - - /* test that strintern works */ - const char *i1 = strintern(p1); - const char *i2 = strintern(p1); - if (strcmp(i1, p1)) - printf("strintern(%s) returns %s\n", p1, i1); - else if (i1 == p1) - printf("strintern(%s) returns input pointer\n", p1); - else if (i1 != i2) - printf("strintern(%s) != strintern(%s)", i1, i2); - else - printf("%s\n", i1); - } else if (!strcmp("perfhashmap", cmd) && p1 && p2) { + if (!strcmp("perfhashmap", cmd) && p1 && p2) { perf_hashmap(atoi(p1), atoi(p2)); @@ -270,6 +175,5 @@ int cmd__hashmap(int argc, const char **argv) string_list_clear(&parts, 0); strbuf_release(&line); - hashmap_clear_and_free(&map, struct test_entry, ent); return 0; } diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c index ed52eb76bf..a288069b04 100644 --- a/t/helper/test-json-writer.c +++ b/t/helper/test-json-writer.c @@ -415,6 +415,7 @@ static void get_i(struct line *line, intmax_t *s_in) get_s(line, &s); + errno = 0; *s_in = strtol(s, &endptr, 10); if (*endptr || errno == ERANGE) die("line[%d]: invalid integer value", line->nr); @@ -427,6 +428,7 @@ static void get_d(struct line *line, double *s_in) get_s(line, &s); + errno = 0; *s_in = strtod(s, &endptr); if (*endptr || errno == ERANGE) die("line[%d]: invalid float value", line->nr); diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c index 42ccc87051..328bfe2977 100644 --- a/t/helper/test-mergesort.c +++ b/t/helper/test-mergesort.c @@ -122,7 +122,7 @@ static const struct dist *get_dist_by_name(const char *name) return NULL; } -static void mode_copy(int *arr, int n) +static void mode_copy(int *arr UNUSED, int n UNUSED) { /* nothing */ } diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c deleted file mode 100644 index 076b849cbf..0000000000 --- a/t/helper/test-oid-array.c +++ /dev/null @@ -1,49 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-tool.h" -#include "hex.h" -#include "oid-array.h" -#include "setup.h" -#include "strbuf.h" - -static int print_oid(const struct object_id *oid, void *data UNUSED) -{ - puts(oid_to_hex(oid)); - return 0; -} - -int cmd__oid_array(int argc UNUSED, const char **argv UNUSED) -{ - struct oid_array array = OID_ARRAY_INIT; - struct strbuf line = STRBUF_INIT; - int nongit_ok; - - setup_git_directory_gently(&nongit_ok); - if (nongit_ok) - repo_set_hash_algo(the_repository, GIT_HASH_SHA1); - - while (strbuf_getline(&line, stdin) != EOF) { - const char *arg; - struct object_id oid; - - if (skip_prefix(line.buf, "append ", &arg)) { - if (get_oid_hex(arg, &oid)) - die("not a hexadecimal oid: %s", arg); - oid_array_append(&array, &oid); - } else if (skip_prefix(line.buf, "lookup ", &arg)) { - if (get_oid_hex(arg, &oid)) - die("not a hexadecimal oid: %s", arg); - printf("%d\n", oid_array_lookup(&array, &oid)); - } else if (!strcmp(line.buf, "clear")) - oid_array_clear(&array); - else if (!strcmp(line.buf, "for_each_unique")) - oid_array_for_each_unique(&array, print_oid, NULL); - else - die("unknown command: %s", line.buf); - } - - strbuf_release(&line); - oid_array_clear(&array); - - return 0; -} diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 5250913d99..5da359486c 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -282,14 +282,16 @@ int cmd__parse_options_flags(int argc, const char **argv) return parse_options_flags__cmd(argc, argv, test_flags); } -static int subcmd_one(int argc, const char **argv, const char *prefix UNUSED) +static int subcmd_one(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { printf("fn: subcmd_one\n"); print_args(argc, argv); return 0; } -static int subcmd_two(int argc, const char **argv, const char *prefix UNUSED) +static int subcmd_two(int argc, const char **argv, const char *prefix UNUSED, + struct repository *repo UNUSED) { printf("fn: subcmd_two\n"); print_args(argc, argv); @@ -319,7 +321,7 @@ static int parse_subcommand__cmd(int argc, const char **argv, printf("opt: %d\n", opt); - return fn(argc, argv, NULL); + return fn(argc, argv, NULL, NULL); } int cmd__parse_subcommand(int argc, const char **argv) diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c index 0ead529167..a1af9710c3 100644 --- a/t/helper/test-partial-clone.c +++ b/t/helper/test-partial-clone.c @@ -26,6 +26,8 @@ static void object_info(const char *gitdir, const char *oid_hex) if (oid_object_info_extended(&r, &oid, &oi, 0)) die("could not obtain object info"); printf("%d\n", (int) size); + + repo_clear(&r); } int cmd__partial_clone(int argc, const char **argv) diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index bf0e23ed50..3129aa28fd 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "test-tool.h" #include "abspath.h" #include "environment.h" @@ -38,7 +40,7 @@ static void normalize_argv_string(const char **var, const char *input) *var = input; if (*var && (**var == '<' || **var == '(')) - die("Bad value: %s\n", input); + die("Bad value: %s", input); } struct test_data { @@ -78,12 +80,12 @@ static int test_function(struct test_data *data, char *(*func)(char *input), if (!strcmp(to, data[i].to)) continue; if (!data[i].alternative) - error("FAIL: %s(%s) => '%s' != '%s'\n", + error("FAIL: %s(%s) => '%s' != '%s'", funcname, data[i].from, to, data[i].to); else if (!strcmp(to, data[i].alternative)) continue; else - error("FAIL: %s(%s) => '%s' != '%s', '%s'\n", + error("FAIL: %s(%s) => '%s' != '%s', '%s'", funcname, data[i].from, to, data[i].to, data[i].alternative); failed = 1; diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c index 29361c7aab..3703f734f3 100644 --- a/t/helper/test-proc-receive.c +++ b/t/helper/test-proc-receive.c @@ -196,5 +196,12 @@ int cmd__proc_receive(int argc, const char **argv) packet_flush(1); sigchain_pop(SIGPIPE); + while (commands) { + struct command *next = commands->next; + free(commands); + commands = next; + } + string_list_clear(&push_options, 0); + return 0; } diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 66acb6a06c..44be2645e9 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -62,13 +62,13 @@ int cmd__progress(int argc, const char **argv) else if (*end == ' ') title = string_list_insert(&titles, end + 1)->string; else - die("invalid input: '%s'\n", line.buf); + die("invalid input: '%s'", line.buf); progress = start_progress(title, total); } else if (skip_prefix(line.buf, "progress ", (const char **) &end)) { uint64_t item_count = strtoull(end, &end, 10); if (*end != '\0') - die("invalid input: '%s'\n", line.buf); + die("invalid input: '%s'", line.buf); display_progress(progress, item_count); } else if (skip_prefix(line.buf, "throughput ", (const char **) &end)) { @@ -76,10 +76,10 @@ int cmd__progress(int argc, const char **argv) byte_count = strtoull(end, &end, 10); if (*end != ' ') - die("invalid input: '%s'\n", line.buf); + die("invalid input: '%s'", line.buf); test_ms = strtoull(end + 1, &end, 10); if (*end != '\0') - die("invalid input: '%s'\n", line.buf); + die("invalid input: '%s'", line.buf); progress_test_ns = test_ms * 1000 * 1000; display_throughput(progress, byte_count); } else if (!strcmp(line.buf, "update")) { @@ -87,7 +87,7 @@ int cmd__progress(int argc, const char **argv) } else if (!strcmp(line.buf, "stop")) { stop_progress(&progress); } else { - die("invalid input: '%s'\n", line.buf); + die("invalid input: '%s'", line.buf); } } strbuf_release(&line); diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 5dd374379c..84deee604a 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -67,13 +67,13 @@ int cmd__reach(int ac, const char **av) peeled = deref_tag_noverify(the_repository, orig); if (!peeled) - die("failed to load commit for input %s resulting in oid %s\n", + die("failed to load commit for input %s resulting in oid %s", buf.buf, oid_to_hex(&oid)); c = object_as_type(peeled, OBJ_COMMIT, 0); if (!c) - die("failed to load commit for input %s resulting in oid %s\n", + die("failed to load commit for input %s resulting in oid %s", buf.buf, oid_to_hex(&oid)); switch (buf.buf[0]) { @@ -116,6 +116,8 @@ int cmd__reach(int ac, const char **av) repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0)); else if (!strcmp(av[1], "is_descendant_of")) printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X)); + else if (!strcmp(av[1], "get_branch_base_for_tip")) + printf("%s(A,X):%d\n", av[1], get_branch_base_for_tip(r, A, X_array, X_nr)); else if (!strcmp(av[1], "get_merge_bases_many")) { struct commit_list *list = NULL; if (repo_get_merge_bases_many(the_repository, @@ -125,10 +127,12 @@ int cmd__reach(int ac, const char **av) exit(128); printf("%s(A,X):\n", av[1]); print_sorted_commit_ids(list); + free_commit_list(list); } else if (!strcmp(av[1], "reduce_heads")) { struct commit_list *list = reduce_heads(X); printf("%s(X):\n", av[1]); print_sorted_commit_ids(list); + free_commit_list(list); } else if (!strcmp(av[1], "can_all_from_reach")) { printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1)); } else if (!strcmp(av[1], "can_all_from_reach_with_flag")) { @@ -151,6 +155,7 @@ int cmd__reach(int ac, const char **av) filter.with_commit_tag_algo = 0; printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache)); + clear_contains_cache(&cache); } else if (!strcmp(av[1], "get_reachable_subset")) { const int reachable_flag = 1; int i, count = 0; @@ -174,7 +179,14 @@ int cmd__reach(int ac, const char **av) die(_("too many commits marked reachable")); print_sorted_commit_ids(list); + free_commit_list(list); } + object_array_clear(&X_obj); + strbuf_release(&buf); + free_commit_list(X); + free_commit_list(Y); + free(X_array); + free(Y_array); return 0; } diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index d285c656bd..e277dde8e7 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -11,8 +11,6 @@ int cmd__read_cache(int argc, const char **argv) int i, cnt = 1; const char *name = NULL; - initialize_repository(the_repository); - if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) { argc--; argv++; diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 9018c9f541..811dde1cb3 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -97,7 +97,6 @@ int cmd__read_graph(int argc, const char **argv) } done: - UNLEAK(graph); - + free_commit_graph(graph); return ret; } diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index 83effc2b5f..fc63236961 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -9,18 +9,27 @@ #include "packfile.h" #include "setup.h" #include "gettext.h" +#include "pack-revindex.h" -static int read_midx_file(const char *object_dir, int show_objects) +static int read_midx_file(const char *object_dir, const char *checksum, + int show_objects) { uint32_t i; struct multi_pack_index *m; setup_git_directory(); - m = load_multi_pack_index(object_dir, 1); + m = load_multi_pack_index(the_repository, object_dir, 1); if (!m) return 1; + if (checksum) { + while (m && strcmp(hash_to_hex(get_midx_checksum(m)), checksum)) + m = m->base_midx; + if (!m) + return 1; + } + printf("header: %08x %d %d %d %d\n", m->signature, m->version, @@ -54,7 +63,8 @@ static int read_midx_file(const char *object_dir, int show_objects) struct pack_entry e; for (i = 0; i < m->num_objects; i++) { - nth_midxed_object_oid(&oid, m, i); + nth_midxed_object_oid(&oid, m, + i + m->num_objects_in_base); fill_midx_entry(the_repository, &oid, &e, m); printf("%s %"PRIu64"\t%s\n", @@ -72,10 +82,12 @@ static int read_midx_checksum(const char *object_dir) struct multi_pack_index *m; setup_git_directory(); - m = load_multi_pack_index(object_dir, 1); + m = load_multi_pack_index(the_repository, object_dir, 1); if (!m) return 1; printf("%s\n", hash_to_hex(get_midx_checksum(m))); + + close_midx(m); return 0; } @@ -86,16 +98,18 @@ static int read_midx_preferred_pack(const char *object_dir) setup_git_directory(); - midx = load_multi_pack_index(object_dir, 1); + midx = load_multi_pack_index(the_repository, object_dir, 1); if (!midx) return 1; if (midx_preferred_pack(midx, &preferred_pack) < 0) { warning(_("could not determine MIDX preferred pack")); + close_midx(midx); return 1; } printf("%s\n", midx->pack_names[preferred_pack]); + close_midx(midx); return 0; } @@ -107,13 +121,15 @@ static int read_midx_bitmapped_packs(const char *object_dir) setup_git_directory(); - midx = load_multi_pack_index(object_dir, 1); + midx = load_multi_pack_index(the_repository, object_dir, 1); if (!midx) return 1; - for (i = 0; i < midx->num_packs; i++) { - if (nth_bitmapped_pack(the_repository, midx, &pack, i) < 0) + for (i = 0; i < midx->num_packs + midx->num_packs_in_base; i++) { + if (nth_bitmapped_pack(the_repository, midx, &pack, i) < 0) { + close_midx(midx); return 1; + } printf("%s\n", pack_basename(pack.p)); printf(" bitmap_pos: %"PRIuMAX"\n", (uintmax_t)pack.bitmap_pos); @@ -127,16 +143,16 @@ static int read_midx_bitmapped_packs(const char *object_dir) int cmd__read_midx(int argc, const char **argv) { - if (!(argc == 2 || argc == 3)) - usage("read-midx [--show-objects|--checksum|--preferred-pack|--bitmap] <object-dir>"); + if (!(argc == 2 || argc == 3 || argc == 4)) + usage("read-midx [--show-objects|--checksum|--preferred-pack|--bitmap] <object-dir> <checksum>"); if (!strcmp(argv[1], "--show-objects")) - return read_midx_file(argv[2], 1); + return read_midx_file(argv[2], argv[3], 1); else if (!strcmp(argv[1], "--checksum")) return read_midx_checksum(argv[2]); else if (!strcmp(argv[1], "--preferred-pack")) return read_midx_preferred_pack(argv[2]); else if (!strcmp(argv[1], "--bitmap")) return read_midx_bitmapped_packs(argv[2]); - return read_midx_file(argv[1], 0); + return read_midx_file(argv[1], argv[2], 0); } diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 637b8b294e..240f6fc29d 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -156,7 +156,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv) return refs_rename_ref(refs, oldref, newref, logmsg); } -static int each_ref(const char *refname, const struct object_id *oid, +static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags, void *cb_data UNUSED) { printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags); @@ -199,7 +199,7 @@ static int cmd_verify_ref(struct ref_store *refs, const char **argv) struct strbuf err = STRBUF_INIT; int ret; - ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err); + ret = refs_verify_refname_available(refs, refname, NULL, NULL, 0, &err); if (err.len) puts(err.buf); return ret; diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index aa6538a8da..3c72ed985b 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -1,20 +1,200 @@ +#include "git-compat-util.h" +#include "hash.h" +#include "hex.h" #include "reftable/system.h" -#include "reftable/reftable-tests.h" +#include "reftable/reftable-error.h" +#include "reftable/reftable-merged.h" +#include "reftable/reftable-reader.h" +#include "reftable/reftable-stack.h" #include "test-tool.h" -int cmd__reftable(int argc, const char **argv) +static void print_help(void) { - /* test from simple to complex. */ - block_test_main(argc, argv); - tree_test_main(argc, argv); - pq_test_main(argc, argv); - readwrite_test_main(argc, argv); - merged_test_main(argc, argv); - stack_test_main(argc, argv); + printf("usage: dump [-st] arg\n\n" + "options: \n" + " -b dump blocks\n" + " -t dump table\n" + " -s dump stack\n" + " -6 sha256 hash format\n" + " -h this help\n" + "\n"); +} + +static int dump_table(struct reftable_merged_table *mt) +{ + struct reftable_iterator it = { NULL }; + struct reftable_ref_record ref = { NULL }; + struct reftable_log_record log = { NULL }; + const struct git_hash_algo *algop; + int err; + + err = reftable_merged_table_init_ref_iterator(mt, &it); + if (err < 0) + return err; + + err = reftable_iterator_seek_ref(&it, ""); + if (err < 0) + return err; + + algop = &hash_algos[hash_algo_by_id(reftable_merged_table_hash_id(mt))]; + + while (1) { + err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) + break; + if (err < 0) + return err; + + printf("ref{%s(%" PRIu64 ") ", ref.refname, ref.update_index); + switch (ref.value_type) { + case REFTABLE_REF_SYMREF: + printf("=> %s", ref.value.symref); + break; + case REFTABLE_REF_VAL2: + printf("val 2 %s", hash_to_hex_algop(ref.value.val2.value, algop)); + printf("(T %s)", hash_to_hex_algop(ref.value.val2.target_value, algop)); + break; + case REFTABLE_REF_VAL1: + printf("val 1 %s", hash_to_hex_algop(ref.value.val1, algop)); + break; + case REFTABLE_REF_DELETION: + printf("delete"); + break; + } + printf("}\n"); + } + reftable_iterator_destroy(&it); + reftable_ref_record_release(&ref); + + err = reftable_merged_table_init_log_iterator(mt, &it); + if (err < 0) + return err; + + err = reftable_iterator_seek_log(&it, ""); + if (err < 0) + return err; + + while (1) { + err = reftable_iterator_next_log(&it, &log); + if (err > 0) + break; + if (err < 0) + return err; + + switch (log.value_type) { + case REFTABLE_LOG_DELETION: + printf("log{%s(%" PRIu64 ") delete\n", log.refname, + log.update_index); + break; + case REFTABLE_LOG_UPDATE: + printf("log{%s(%" PRIu64 ") %s <%s> %" PRIu64 " %04d\n", + log.refname, log.update_index, + log.value.update.name ? log.value.update.name : "", + log.value.update.email ? log.value.update.email : "", + log.value.update.time, + log.value.update.tz_offset); + printf("%s => ", hash_to_hex_algop(log.value.update.old_hash, algop)); + printf("%s\n\n%s\n}\n", hash_to_hex_algop(log.value.update.new_hash, algop), + log.value.update.message ? log.value.update.message : ""); + break; + } + } + reftable_iterator_destroy(&it); + reftable_log_record_release(&log); return 0; } +static int dump_stack(const char *stackdir, uint32_t hash_id) +{ + struct reftable_stack *stack = NULL; + struct reftable_write_options opts = { .hash_id = hash_id }; + struct reftable_merged_table *merged = NULL; + + int err = reftable_new_stack(&stack, stackdir, &opts); + if (err < 0) + goto done; + + merged = reftable_stack_merged_table(stack); + err = dump_table(merged); +done: + if (stack) + reftable_stack_destroy(stack); + return err; +} + +static int dump_reftable(const char *tablename) +{ + struct reftable_block_source src = { 0 }; + struct reftable_merged_table *mt = NULL; + struct reftable_reader *r = NULL; + int err; + + err = reftable_block_source_from_file(&src, tablename); + if (err < 0) + goto done; + + err = reftable_reader_new(&r, &src, tablename); + if (err < 0) + goto done; + + err = reftable_merged_table_new(&mt, &r, 1, + reftable_reader_hash_id(r)); + if (err < 0) + goto done; + + err = dump_table(mt); + +done: + reftable_merged_table_free(mt); + reftable_reader_decref(r); + return err; +} + int cmd__dump_reftable(int argc, const char **argv) { - return reftable_dump_main(argc, (char *const *)argv); + int err = 0; + int opt_dump_blocks = 0; + int opt_dump_table = 0; + int opt_dump_stack = 0; + uint32_t opt_hash_id = REFTABLE_HASH_SHA1; + const char *arg = NULL, *argv0 = argv[0]; + + for (; argc > 1; argv++, argc--) + if (*argv[1] != '-') + break; + else if (!strcmp("-b", argv[1])) + opt_dump_blocks = 1; + else if (!strcmp("-t", argv[1])) + opt_dump_table = 1; + else if (!strcmp("-6", argv[1])) + opt_hash_id = REFTABLE_HASH_SHA256; + else if (!strcmp("-s", argv[1])) + opt_dump_stack = 1; + else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) { + print_help(); + return 2; + } + + if (argc != 2) { + fprintf(stderr, "need argument\n"); + print_help(); + return 2; + } + + arg = argv[1]; + + if (opt_dump_blocks) { + err = reftable_reader_print_blocks(arg); + } else if (opt_dump_table) { + err = dump_reftable(arg); + } else if (opt_dump_stack) { + err = dump_stack(arg, opt_hash_id); + } + + if (err < 0) { + fprintf(stderr, "%s: %s: %s\n", argv0, arg, + reftable_error_str(err)); + return 1; + } + return 0; } diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c index 7e1d9e0ee4..ff407b575c 100644 --- a/t/helper/test-rot13-filter.c +++ b/t/helper/test-rot13-filter.c @@ -9,7 +9,7 @@ * ("clean", "smudge", etc). * * When --always-delay is given all pathnames with the "can-delay" flag - * that don't appear on the list bellow are delayed with a count of 1 + * that don't appear on the list below are delayed with a count of 1 * (see more below). * * This implementation supports special test cases: diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c index 6ca069ce63..6dce957153 100644 --- a/t/helper/test-submodule-nested-repo-config.c +++ b/t/helper/test-submodule-nested-repo-config.c @@ -29,6 +29,6 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv) print_config_from_gitmodules(&subrepo, argv[2]); submodule_free(the_repository); - + repo_clear(&subrepo); return 0; } diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index da3e69128a..1ebb69a5dc 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -26,6 +26,7 @@ static struct test_cmd cmds[] = { { "drop-caches", cmd__drop_caches }, { "dump-cache-tree", cmd__dump_cache_tree }, { "dump-fsmonitor", cmd__dump_fsmonitor }, + { "dump-reftable", cmd__dump_reftable }, { "dump-split-index", cmd__dump_split_index }, { "dump-untracked-cache", cmd__dump_untracked_cache }, { "env-helper", cmd__env_helper }, @@ -43,7 +44,6 @@ static struct test_cmd cmds[] = { { "match-trees", cmd__match_trees }, { "mergesort", cmd__mergesort }, { "mktemp", cmd__mktemp }, - { "oid-array", cmd__oid_array }, { "online-cpus", cmd__online_cpus }, { "pack-mtimes", cmd__pack_mtimes }, { "parse-options", cmd__parse_options }, @@ -61,9 +61,7 @@ static struct test_cmd cmds[] = { { "read-graph", cmd__read_graph }, { "read-midx", cmd__read_midx }, { "ref-store", cmd__ref_store }, - { "reftable", cmd__reftable }, { "rot13-filter", cmd__rot13_filter }, - { "dump-reftable", cmd__dump_reftable }, { "regex", cmd__regex }, { "repository", cmd__repository }, { "revision-walking", cmd__revision_walking }, @@ -83,7 +81,6 @@ static struct test_cmd cmds[] = { { "trace2", cmd__trace2 }, { "truncate", cmd__truncate }, { "userdiff", cmd__userdiff }, - { "urlmatch-normalization", cmd__urlmatch_normalization }, { "xml-encode", cmd__xml_encode }, { "wildmatch", cmd__wildmatch }, #ifdef GIT_WINDOWS_NATIVE diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 642a34578c..21802ac27d 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -55,7 +55,6 @@ int cmd__read_graph(int argc, const char **argv); int cmd__read_midx(int argc, const char **argv); int cmd__ref_store(int argc, const char **argv); int cmd__rot13_filter(int argc, const char **argv); -int cmd__reftable(int argc, const char **argv); int cmd__regex(int argc, const char **argv); int cmd__repository(int argc, const char **argv); int cmd__revision_walking(int argc, const char **argv); @@ -64,7 +63,6 @@ int cmd__scrap_cache_tree(int argc, const char **argv); int cmd__serve_v2(int argc, const char **argv); int cmd__sha1(int argc, const char **argv); int cmd__sha1_is_sha1dc(int argc, const char **argv); -int cmd__oid_array(int argc, const char **argv); int cmd__sha256(int argc, const char **argv); int cmd__sigchain(int argc, const char **argv); int cmd__simple_ipc(int argc, const char **argv); @@ -76,7 +74,6 @@ int cmd__subprocess(int argc, const char **argv); int cmd__trace2(int argc, const char **argv); int cmd__truncate(int argc, const char **argv); int cmd__userdiff(int argc, const char **argv); -int cmd__urlmatch_normalization(int argc, const char **argv); int cmd__xml_encode(int argc, const char **argv); int cmd__wildmatch(int argc, const char **argv); #ifdef GIT_WINDOWS_NATIVE diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c index cd955ec63e..c588c273ce 100644 --- a/t/helper/test-trace2.c +++ b/t/helper/test-trace2.c @@ -26,6 +26,7 @@ static int get_i(int *p_value, const char *data) if (!data || !*data) return MyError; + errno = 0; *p_value = strtol(data, &endptr, 10); if (*endptr || errno == ERANGE) return MyError; diff --git a/t/helper/test-urlmatch-normalization.c b/t/helper/test-urlmatch-normalization.c deleted file mode 100644 index 86edd454f5..0000000000 --- a/t/helper/test-urlmatch-normalization.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "test-tool.h" -#include "git-compat-util.h" -#include "urlmatch.h" - -int cmd__urlmatch_normalization(int argc, const char **argv) -{ - const char usage[] = "test-tool urlmatch-normalization [-p | -l] <url1> | <url1> <url2>"; - char *url1 = NULL, *url2 = NULL; - int opt_p = 0, opt_l = 0; - int ret = 0; - - /* - * For one url, succeed if url_normalize succeeds on it, fail otherwise. - * For two urls, succeed only if url_normalize succeeds on both and - * the results compare equal with strcmp. If -p is given (one url only) - * and url_normalize succeeds, print the result followed by "\n". If - * -l is given (one url only) and url_normalize succeeds, print the - * returned length in decimal followed by "\n". - */ - - if (argc > 1 && !strcmp(argv[1], "-p")) { - opt_p = 1; - argc--; - argv++; - } else if (argc > 1 && !strcmp(argv[1], "-l")) { - opt_l = 1; - argc--; - argv++; - } - - if (argc < 2 || argc > 3) - die("%s", usage); - - if (argc == 2) { - struct url_info info; - url1 = url_normalize(argv[1], &info); - if (!url1) - return 1; - if (opt_p) - printf("%s\n", url1); - if (opt_l) - printf("%u\n", (unsigned)info.url_len); - goto cleanup; - } - - if (opt_p || opt_l) - die("%s", usage); - - url1 = url_normalize(argv[1], NULL); - url2 = url_normalize(argv[2], NULL); - ret = (url1 && url2 && !strcmp(url1, url2)) ? 0 : 1; -cleanup: - free(url1); - free(url2); - return ret; -} diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c index 0ce31ce59f..94c48ababb 100644 --- a/t/helper/test-userdiff.c +++ b/t/helper/test-userdiff.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "test-tool.h" #include "setup.h" #include "userdiff.h" diff --git a/t/interop/README b/t/interop/README index 72d42bd856..4e0608f857 100644 --- a/t/interop/README +++ b/t/interop/README @@ -83,3 +83,10 @@ You can then use test_expect_success as usual, with a few differences: should create one with the appropriate version of git. At the end of the script, call test_done as usual. + +Some older versions may need a few build knobs tweaked (e.g., ancient +versions of Git no longer build with modern OpenSSL). Your script can +set MAKE_OPTS_A and MAKE_OPTS_B, which will be passed alongside +GIT_INTEROP_MAKE_OPTS. Users can override them per-script by setting +GIT_INTEROP_MAKE_OPTS_{A,B} in the environment, just like they can set +GIT_TEST_VERSION_{A,B}. diff --git a/t/interop/i5500-git-daemon.sh b/t/interop/i5500-git-daemon.sh index 4d22e42f84..88712d1b5d 100755 --- a/t/interop/i5500-git-daemon.sh +++ b/t/interop/i5500-git-daemon.sh @@ -2,6 +2,7 @@ VERSION_A=. VERSION_B=v1.0.0 +MAKE_OPTS_B="NO_OPENSSL=TooOld" : ${LIB_GIT_DAEMON_PORT:=5500} LIB_GIT_DAEMON_COMMAND='git.a daemon' diff --git a/t/interop/interop-lib.sh b/t/interop/interop-lib.sh index 62f4481b6e..1b5864d2a7 100644 --- a/t/interop/interop-lib.sh +++ b/t/interop/interop-lib.sh @@ -45,7 +45,7 @@ build_version () { ( cd "$dir" && - make $GIT_INTEROP_MAKE_OPTS >&2 && + make $2 $GIT_INTEROP_MAKE_OPTS >&2 && touch .built ) || return 1 @@ -76,9 +76,11 @@ generate_wrappers () { VERSION_A=${GIT_TEST_VERSION_A:-$VERSION_A} VERSION_B=${GIT_TEST_VERSION_B:-$VERSION_B} +MAKE_OPTS_A=${GIT_INTEROP_MAKE_OPTS_A:-$MAKE_OPTS_A} +MAKE_OPTS_B=${GIT_INTEROP_MAKE_OPTS_B:-$MAKE_OPTS_B} -if ! DIR_A=$(build_version "$VERSION_A") || - ! DIR_B=$(build_version "$VERSION_B") +if ! DIR_A=$(build_version "$VERSION_A" "$MAKE_OPTS_A") || + ! DIR_B=$(build_version "$VERSION_B" "$MAKE_OPTS_B") then echo >&2 "fatal: unable to build git versions" exit 1 diff --git a/t/lib-bitmap.sh b/t/lib-bitmap.sh index f595937094..62aa6744a6 100644 --- a/t/lib-bitmap.sh +++ b/t/lib-bitmap.sh @@ -1,6 +1,8 @@ # Helpers for scripts testing bitmap functionality; see t5310 for # example usage. +. "$TEST_DIRECTORY"/lib-midx.sh + objdir=.git/objects midx=$objdir/pack/multi-pack-index @@ -264,10 +266,6 @@ have_delta () { test_cmp expect actual } -midx_checksum () { - test-tool read-midx --checksum "$1" -} - # midx_pack_source <obj> midx_pack_source () { test-tool read-midx --show-objects .git/objects | grep "^$1 " | cut -f2 diff --git a/t/lib-bundle.sh b/t/lib-bundle.sh index cf7ed818b2..62b7bb13c8 100644 --- a/t/lib-bundle.sh +++ b/t/lib-bundle.sh @@ -11,7 +11,7 @@ convert_bundle_to_pack () { } # Check count of objects in a bundle file. -# We can use "--thin" opiton to check thin pack, which must be fixed by +# We can use "--thin" option to check thin pack, which must be fixed by # command `git-index-pack --fix-thin --stdin`. test_bundle_object_count () { thin= diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index ea28971e8e..2fde2353fd 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -1,7 +1,3 @@ -if test -z "$TEST_FAILS_SANITIZE_LEAK" -then - TEST_PASSES_SANITIZE_LEAK=true -fi . ./test-lib.sh if test -n "$NO_SVN_TESTS" diff --git a/t/lib-gitweb.sh b/t/lib-gitweb.sh index 1f32ca66ea..7f9808ec20 100644 --- a/t/lib-gitweb.sh +++ b/t/lib-gitweb.sh @@ -48,8 +48,8 @@ EOF test -f "$SCRIPT_NAME" || error "Cannot find gitweb at $GITWEB_TEST_INSTALLED." say "# Testing $SCRIPT_NAME" - else # normal case, use source version of gitweb - SCRIPT_NAME="$GIT_BUILD_DIR/gitweb/gitweb.perl" + else # normal case, use built version of gitweb + SCRIPT_NAME="$GIT_BUILD_DIR/gitweb/gitweb.cgi" fi export SCRIPT_NAME } diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index add11e88fc..3845b6ac44 100644 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -6,7 +6,7 @@ # executed in an eval'ed subshell that changes the working directory to a # temporary one. -GNUPGHOME="$PWD/gpghome" +GNUPGHOME="$(pwd)/gpghome" export GNUPGHOME test_lazy_prereq GPG ' diff --git a/t/lib-midx.sh b/t/lib-midx.sh index 1261994744..e38c609604 100644 --- a/t/lib-midx.sh +++ b/t/lib-midx.sh @@ -6,3 +6,31 @@ test_midx_consistent () { test_cmp expect actual && git multi-pack-index --object-dir=$1 verify } + +midx_checksum () { + test-tool read-midx --checksum "$1" +} + +midx_git_two_modes () { + git -c core.multiPackIndex=false $1 >expect && + git -c core.multiPackIndex=true $1 >actual && + if [ "$2" = "sorted" ] + then + sort <expect >expect.sorted && + mv expect.sorted expect && + sort <actual >actual.sorted && + mv actual.sorted actual + fi && + test_cmp expect actual +} + +compare_results_with_midx () { + MSG=$1 + test_expect_success "check normal git operations: $MSG" ' + midx_git_two_modes "rev-list --objects --all" && + midx_git_two_modes "log --raw" && + midx_git_two_modes "count-objects --verbose" && + midx_git_two_modes "cat-file --batch-all-objects --batch-check" && + midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted + ' +} diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 11d2dc9fe3..0dd764310d 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -187,7 +187,7 @@ set_reword_editor () { exit 1 fi fi && - # There should be no uncommited changes + # There should be no uncommitted changes git diff --exit-code HEAD && # The todo-list should be re-read after a reword GIT_SEQUENCE_EDITOR="\"$PWD/reword-sequence-editor.sh\"" \ diff --git a/t/lib-sudo.sh b/t/lib-sudo.sh index b4d7788f4e..477e0fdc04 100644 --- a/t/lib-sudo.sh +++ b/t/lib-sudo.sh @@ -6,7 +6,7 @@ run_with_sudo () { local RUN="$TEST_DIRECTORY/$$.sh" write_script "$RUN" "$TEST_SHELL_PATH" # avoid calling "$RUN" directly so sudo doesn't get a chance to - # override the shell, add aditional restrictions or even reject + # override the shell, add additional restrictions or even reject # running the script because its security policy deem it unsafe sudo "$TEST_SHELL_PATH" -c "\"$RUN\"" ret=$? diff --git a/t/lib-unicode-nfc-nfd.sh b/t/lib-unicode-nfc-nfd.sh index 22232247ef..aed0a4dd44 100755 --- a/t/lib-unicode-nfc-nfd.sh +++ b/t/lib-unicode-nfc-nfd.sh @@ -74,7 +74,7 @@ test_lazy_prereq UNICODE_NFD_PRESERVED ' # Yielding: \xcf \x89 + \xcc \x94 + \xcd \x82 # # Note that I've used the canonical ordering of the -# combinining characters. It is also possible to +# combining characters. It is also possible to # swap them. My testing shows that that non-standard # ordering also causes a collision in mkdir. However, # the resulting names don't draw correctly on the diff --git a/t/perf/p1500-graph-walks.sh b/t/perf/p1500-graph-walks.sh index e14e7620cc..5b23ce5db9 100755 --- a/t/perf/p1500-graph-walks.sh +++ b/t/perf/p1500-graph-walks.sh @@ -20,6 +20,21 @@ test_expect_success 'setup' ' echo tag-$ref || return 1 done >tags && + + echo "A:HEAD" >test-tool-refs && + for line in $(cat refs) + do + echo "X:$line" >>test-tool-refs || return 1 + done && + echo "A:HEAD" >test-tool-tags && + for line in $(cat tags) + do + echo "X:$line" >>test-tool-tags || return 1 + done && + + commit=$(git commit-tree $(git rev-parse HEAD^{tree})) && + git update-ref refs/heads/disjoint-base $commit && + git commit-graph write --reachable ' @@ -47,4 +62,20 @@ test_perf 'contains: git tag --merged' ' xargs git tag --merged=HEAD <tags ' +test_perf 'is-base check: test-tool reach (refs)' ' + test-tool reach get_branch_base_for_tip <test-tool-refs +' + +test_perf 'is-base check: test-tool reach (tags)' ' + test-tool reach get_branch_base_for_tip <test-tool-tags +' + +test_perf 'is-base check: git for-each-ref' ' + git for-each-ref --format="%(is-base:HEAD)" --stdin <refs +' + +test_perf 'is-base check: git for-each-ref (disjoint-base)' ' + git for-each-ref --format="%(is-base:refs/heads/disjoint-base)" --stdin <refs +' + test_done diff --git a/t/perf/p5311-pack-bitmaps-fetch.sh b/t/perf/p5311-pack-bitmaps-fetch.sh index 426fab87e3..047efb995d 100755 --- a/t/perf/p5311-pack-bitmaps-fetch.sh +++ b/t/perf/p5311-pack-bitmaps-fetch.sh @@ -39,7 +39,7 @@ test_fetch_bitmaps () { ' test_size "size $title" ' - wc -c <tmp.pack + test_file_size tmp.pack ' test_perf "client $title (lookup=$1)" ' diff --git a/t/perf/p5332-multi-pack-reuse.sh b/t/perf/p5332-multi-pack-reuse.sh index 5c6c575d62..d1c89a8b7d 100755 --- a/t/perf/p5332-multi-pack-reuse.sh +++ b/t/perf/p5332-multi-pack-reuse.sh @@ -73,7 +73,7 @@ do " test_size "clone size for $nr_packs-pack scenario ($reuse-pack reuse)" ' - wc -c <result + test_file_size result ' done done diff --git a/t/perf/p6100-describe.sh b/t/perf/p6100-describe.sh new file mode 100755 index 0000000000..069f91ce49 --- /dev/null +++ b/t/perf/p6100-describe.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='performance of git-describe' +. ./perf-lib.sh + +test_perf_default_repo + +# clear out old tags and give us a known state +test_expect_success 'set up tags' ' + git for-each-ref --format="delete %(refname)" refs/tags >to-delete && + git update-ref --stdin <to-delete && + new=$(git rev-list -1000 HEAD | tail -n 1) && + git tag -m new new $new && + old=$(git rev-list HEAD | tail -n 1) && + git tag -m old old $old +' + +test_perf 'describe HEAD' ' + git describe HEAD +' + +test_perf 'describe HEAD with one max candidate' ' + git describe --candidates=1 HEAD +' + +test_perf 'describe HEAD with one tag' ' + git describe --match=new HEAD +' + +test_done diff --git a/t/perf/p7527-builtin-fsmonitor.sh b/t/perf/p7527-builtin-fsmonitor.sh index c3f9a4caa4..90164327e8 100755 --- a/t/perf/p7527-builtin-fsmonitor.sh +++ b/t/perf/p7527-builtin-fsmonitor.sh @@ -95,7 +95,7 @@ test_expect_success "Setup borrowed repo (fsm+uc)" " # time is not useful. # # Create a temp branch and do all work relative to it so that we don't -# accidentially alter the real ballast branch. +# accidentally alter the real ballast branch. # test_expect_success "Setup borrowed repo (temp ballast branch)" " test_might_fail git -C $REPO checkout $BALLAST_BR && diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index ab0c763411..8ab6d9c469 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -282,7 +282,7 @@ test_perf_ () { # Run the performance test script specified in perf-test with # optional prerequisite and setup steps. # Options: -# --prereq prerequisites: Skip the test if prequisites aren't met +# --prereq prerequisites: Skip the test if prerequisites aren't met # --setup "setup-steps": Run setup steps prior to each measured iteration # test_perf () { @@ -309,7 +309,7 @@ test_size_ () { # prerequisites and setup steps. Returns the numeric value # returned by size-test. # Options: -# --prereq prerequisites: Skip the test if prequisites aren't met +# --prereq prerequisites: Skip the test if prerequisites aren't met # --setup "setup-steps": Run setup steps prior to the size measurement test_size () { diff --git a/t/run-test.sh b/t/run-test.sh index 13c353b91b..63328ac630 100755 --- a/t/run-test.sh +++ b/t/run-test.sh @@ -10,7 +10,7 @@ case "$1" in echo >&2 "ERROR: TEST_SHELL_PATH is empty or not set" exit 1 fi - exec "${TEST_SHELL_PATH}" "$@" + exec "${TEST_SHELL_PATH}" "$@" ${TEST_OPTIONS} ;; *) exec "$@" diff --git a/t/socks4-proxy.pl b/t/socks4-proxy.pl new file mode 100644 index 0000000000..4c3a35c008 --- /dev/null +++ b/t/socks4-proxy.pl @@ -0,0 +1,48 @@ +use strict; +use IO::Select; +use IO::Socket::UNIX; +use IO::Socket::INET; + +my $path = shift; + +unlink($path); +my $server = IO::Socket::UNIX->new(Listen => 1, Local => $path) + or die "unable to listen on $path: $!"; + +$| = 1; +print "ready\n"; + +while (my $client = $server->accept()) { + sysread $client, my $buf, 8; + my ($version, $cmd, $port, $ip) = unpack 'CCnN', $buf; + next unless $version == 4; # socks4 + next unless $cmd == 1; # TCP stream connection + + # skip NUL-terminated id + while (sysread $client, my $char, 1) { + last unless ord($char); + } + + # version(0), reply(5a == granted), port (ignored), ip (ignored) + syswrite $client, "\x00\x5a\x00\x00\x00\x00\x00\x00"; + + my $remote = IO::Socket::INET->new(PeerHost => $ip, PeerPort => $port) + or die "unable to connect to $ip/$port: $!"; + + my $io = IO::Select->new($client, $remote); + while ($io->count) { + for my $fh ($io->can_read(0)) { + for my $pair ([$client, $remote], [$remote, $client]) { + my ($from, $to) = @$pair; + next unless $fh == $from; + + my $r = sysread $from, my $buf, 1024; + if (!defined $r || $r <= 0) { + $io->remove($from); + next; + } + syswrite $to, $buf; + } + } + } +} diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 98b81e4d63..35c5c2b4f9 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -684,7 +684,7 @@ test_expect_success 'subtest: tests respect lazy prerequisites' ' write_and_run_sub_test_lib_test lazy-prereqs <<-\EOF && test_lazy_prereq LAZY_TRUE true - test_expect_success LAZY_TRUE "lazy prereq is satisifed" "true" + test_expect_success LAZY_TRUE "lazy prereq is satisfied" "true" test_expect_success !LAZY_TRUE "negative lazy prereq" "false" test_lazy_prereq LAZY_FALSE false @@ -695,7 +695,7 @@ test_expect_success 'subtest: tests respect lazy prerequisites' ' EOF check_sub_test_lib_test lazy-prereqs <<-\EOF - ok 1 - lazy prereq is satisifed + ok 1 - lazy prereq is satisfied ok 2 # skip negative lazy prereq (missing !LAZY_TRUE) ok 3 # skip lazy prereq not satisfied (missing LAZY_FALSE) ok 4 - negative false prereq diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 49e9bf77c6..72a0c2e7d4 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -2,7 +2,6 @@ test_description='git init' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_config () { @@ -434,6 +433,12 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' ' sep_git_dir_worktree () { test_when_finished "rm -rf mainwt linkwt seprepo" && git init mainwt && + if test "relative" = $2 + then + test_config -C mainwt worktree.useRelativePaths true + else + test_config -C mainwt worktree.useRelativePaths false + fi test_commit -C mainwt gumby && git -C mainwt worktree add --detach ../linkwt && git -C "$1" init --separate-git-dir ../seprepo && @@ -442,12 +447,20 @@ sep_git_dir_worktree () { test_cmp expect actual } -test_expect_success 're-init to move gitdir with linked worktrees' ' - sep_git_dir_worktree mainwt +test_expect_success 're-init to move gitdir with linked worktrees (absolute)' ' + sep_git_dir_worktree mainwt absolute +' + +test_expect_success 're-init to move gitdir within linked worktree (absolute)' ' + sep_git_dir_worktree linkwt absolute ' -test_expect_success 're-init to move gitdir within linked worktree' ' - sep_git_dir_worktree linkwt +test_expect_success 're-init to move gitdir with linked worktrees (relative)' ' + sep_git_dir_worktree mainwt relative +' + +test_expect_success 're-init to move gitdir within linked worktree (relative)' ' + sep_git_dir_worktree linkwt relative ' test_expect_success MINGW '.git hidden' ' @@ -500,6 +513,7 @@ test_expect_success 're-init from a linked worktree' ' ' test_expect_success 'init honors GIT_DEFAULT_HASH' ' + test_when_finished "rm -rf sha1 sha256" && GIT_DEFAULT_HASH=sha1 git init sha1 && git -C sha1 rev-parse --show-object-format >actual && echo sha1 >expected && @@ -511,6 +525,7 @@ test_expect_success 'init honors GIT_DEFAULT_HASH' ' ' test_expect_success 'init honors --object-format' ' + test_when_finished "rm -rf explicit-sha1 explicit-sha256" && git init --object-format=sha1 explicit-sha1 && git -C explicit-sha1 rev-parse --show-object-format >actual && echo sha1 >expected && @@ -521,7 +536,58 @@ test_expect_success 'init honors --object-format' ' test_cmp expected actual ' +test_expect_success 'init honors init.defaultObjectFormat' ' + test_when_finished "rm -rf sha1 sha256" && + + test_config_global init.defaultObjectFormat sha1 && + ( + sane_unset GIT_DEFAULT_HASH && + git init sha1 && + git -C sha1 rev-parse --show-object-format >actual && + echo sha1 >expected && + test_cmp expected actual + ) && + + test_config_global init.defaultObjectFormat sha256 && + ( + sane_unset GIT_DEFAULT_HASH && + git init sha256 && + git -C sha256 rev-parse --show-object-format >actual && + echo sha256 >expected && + test_cmp expected actual + ) +' + +test_expect_success 'init warns about invalid init.defaultObjectFormat' ' + test_when_finished "rm -rf repo" && + test_config_global init.defaultObjectFormat garbage && + + echo "warning: unknown hash algorithm ${SQ}garbage${SQ}" >expect && + git init repo 2>err && + test_cmp expect err && + + git -C repo rev-parse --show-object-format >actual && + echo $GIT_DEFAULT_HASH >expected && + test_cmp expected actual +' + +test_expect_success '--object-format overrides GIT_DEFAULT_HASH' ' + test_when_finished "rm -rf repo" && + GIT_DEFAULT_HASH=sha1 git init --object-format=sha256 repo && + git -C repo rev-parse --show-object-format >actual && + echo sha256 >expected +' + +test_expect_success 'GIT_DEFAULT_HASH overrides init.defaultObjectFormat' ' + test_when_finished "rm -rf repo" && + test_config_global init.defaultObjectFormat sha1 && + GIT_DEFAULT_HASH=sha256 git init repo && + git -C repo rev-parse --show-object-format >actual && + echo sha256 >expected +' + test_expect_success 'extensions.objectFormat is not allowed with repo version 0' ' + test_when_finished "rm -rf explicit-v0" && git init --object-format=sha256 explicit-v0 && git -C explicit-v0 config core.repositoryformatversion 0 && test_must_fail git -C explicit-v0 rev-parse --show-object-format @@ -558,15 +624,6 @@ test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with unknown back grep "invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}garbage${SQ}" err ' -test_expect_success DEFAULT_REPO_FORMAT 'init with GIT_DEFAULT_REF_FORMAT=files' ' - test_when_finished "rm -rf refformat" && - GIT_DEFAULT_REF_FORMAT=files git init refformat && - echo 0 >expect && - git -C refformat config core.repositoryformatversion >actual && - test_cmp expect actual && - test_must_fail git -C refformat config extensions.refstorage -' - test_expect_success 'init with GIT_DEFAULT_REF_FORMAT=garbage' ' test_when_finished "rm -rf refformat" && cat >expect <<-EOF && @@ -576,15 +633,90 @@ test_expect_success 'init with GIT_DEFAULT_REF_FORMAT=garbage' ' test_cmp expect err ' -test_expect_success 'init with --ref-format=files' ' +test_expect_success 'init warns about invalid init.defaultRefFormat' ' + test_when_finished "rm -rf repo" && + test_config_global init.defaultRefFormat garbage && + + echo "warning: unknown ref storage format ${SQ}garbage${SQ}" >expect && + git init repo 2>err && + test_cmp expect err && + + git -C repo rev-parse --show-ref-format >actual && + echo $GIT_DEFAULT_REF_FORMAT >expected && + test_cmp expected actual +' + +backends="files reftable" +for format in $backends +do + test_expect_success DEFAULT_REPO_FORMAT "init with GIT_DEFAULT_REF_FORMAT=$format" ' + test_when_finished "rm -rf refformat" && + GIT_DEFAULT_REF_FORMAT=$format git init refformat && + + if test $format = files + then + test_must_fail git -C refformat config extensions.refstorage && + echo 0 >expect + else + git -C refformat config extensions.refstorage && + echo 1 >expect + fi && + git -C refformat config core.repositoryformatversion >actual && + test_cmp expect actual && + + echo $format >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' + + test_expect_success "init with --ref-format=$format" ' + test_when_finished "rm -rf refformat" && + git init --ref-format=$format refformat && + echo $format >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' + + test_expect_success "init with init.defaultRefFormat=$format" ' + test_when_finished "rm -rf refformat" && + test_config_global init.defaultRefFormat $format && + ( + sane_unset GIT_DEFAULT_REF_FORMAT && + git init refformat + ) && + + echo $format >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' + + test_expect_success "--ref-format=$format overrides GIT_DEFAULT_REF_FORMAT" ' + test_when_finished "rm -rf refformat" && + GIT_DEFAULT_REF_FORMAT=garbage git init --ref-format=$format refformat && + echo $format >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' +done + +test_expect_success "--ref-format= overrides GIT_DEFAULT_REF_FORMAT" ' test_when_finished "rm -rf refformat" && - git init --ref-format=files refformat && - echo files >expect && + GIT_DEFAULT_REF_FORMAT=files git init --ref-format=reftable refformat && + echo reftable >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides init.defaultRefFormat" ' + test_when_finished "rm -rf refformat" && + test_config_global init.defaultRefFormat files && + + GIT_DEFAULT_REF_FORMAT=reftable git init refformat && + echo reftable >expect && git -C refformat rev-parse --show-ref-format >actual && test_cmp expect actual ' -backends="files reftable" for from_format in $backends do test_expect_success "re-init with same format ($from_format)" ' diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh index bf3bf604ab..dfbcdddbcc 100755 --- a/t/t0002-gitfile.sh +++ b/t/t0002-gitfile.sh @@ -7,7 +7,6 @@ Verify that plumbing commands work when .git is a file GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh objpath() { diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 66ccb5889d..3c98b622f2 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -2,7 +2,6 @@ test_description=gitattributes -TEST_PASSES_SANITIZE_LEAK=true TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh index 8114fac73b..3bdafbae0f 100755 --- a/t/t0004-unwritable.sh +++ b/t/t0004-unwritable.sh @@ -2,7 +2,6 @@ test_description='detect unwritable repository and fail correctly' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh index eba75a2490..afba0fc3fc 100755 --- a/t/t0005-signals.sh +++ b/t/t0005-signals.sh @@ -2,7 +2,6 @@ test_description='signals work as we expect' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expect <<EOF diff --git a/t/t0006-date.sh b/t/t0006-date.sh index fd373e1b39..53ced36df4 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -2,7 +2,6 @@ test_description='test date parsing and printing' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # arbitrary reference time: 2009-08-30 19:20:00 diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 9fc5882387..2b60317758 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -2,7 +2,6 @@ test_description='basic sanity checks for git var' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh sane_unset_all_editors () { diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index 02a18d4fdb..c9376dffb5 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -2,7 +2,6 @@ test_description=check-ignore -TEST_PASSES_SANITIZE_LEAK=true TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh index 84172a3739..45229f57b8 100755 --- a/t/t0010-racy-git.sh +++ b/t/t0010-racy-git.sh @@ -2,7 +2,6 @@ test_description='racy GIT' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # This test can give false success if your machine is sufficiently diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh deleted file mode 100755 index 46e74ad107..0000000000 --- a/t/t0011-hashmap.sh +++ /dev/null @@ -1,260 +0,0 @@ -#!/bin/sh - -test_description='test hashmap and string hash functions' - -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -test_hashmap() { - echo "$1" | test-tool hashmap $3 > actual && - echo "$2" > expect && - test_cmp expect actual -} - -test_expect_success 'put' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -put foobarfrotz value4 -size" "NULL -NULL -NULL -NULL -64 4" - -' - -test_expect_success 'put (case insensitive)' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -size" "NULL -NULL -NULL -64 3" ignorecase - -' - -test_expect_success 'replace' ' - -test_hashmap "put key1 value1 -put key1 value2 -put fooBarFrotz value3 -put fooBarFrotz value4 -size" "NULL -value1 -NULL -value3 -64 2" - -' - -test_expect_success 'replace (case insensitive)' ' - -test_hashmap "put key1 value1 -put Key1 value2 -put fooBarFrotz value3 -put foobarfrotz value4 -size" "NULL -value1 -NULL -value3 -64 2" ignorecase - -' - -test_expect_success 'get' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -put foobarfrotz value4 -get key1 -get key2 -get fooBarFrotz -get notInMap" "NULL -NULL -NULL -NULL -value1 -value2 -value3 -NULL" - -' - -test_expect_success 'get (case insensitive)' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -get Key1 -get keY2 -get foobarfrotz -get notInMap" "NULL -NULL -NULL -value1 -value2 -value3 -NULL" ignorecase - -' - -test_expect_success 'add' ' - -test_hashmap "add key1 value1 -add key1 value2 -add fooBarFrotz value3 -add fooBarFrotz value4 -get key1 -get fooBarFrotz -get notInMap" "value2 -value1 -value4 -value3 -NULL" - -' - -test_expect_success 'add (case insensitive)' ' - -test_hashmap "add key1 value1 -add Key1 value2 -add fooBarFrotz value3 -add foobarfrotz value4 -get key1 -get Foobarfrotz -get notInMap" "value2 -value1 -value4 -value3 -NULL" ignorecase - -' - -test_expect_success 'remove' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -remove key1 -remove key2 -remove notInMap -size" "NULL -NULL -NULL -value1 -value2 -NULL -64 1" - -' - -test_expect_success 'remove (case insensitive)' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -remove Key1 -remove keY2 -remove notInMap -size" "NULL -NULL -NULL -value1 -value2 -NULL -64 1" ignorecase - -' - -test_expect_success 'iterate' ' - test-tool hashmap >actual.raw <<-\EOF && - put key1 value1 - put key2 value2 - put fooBarFrotz value3 - iterate - EOF - - cat >expect <<-\EOF && - NULL - NULL - NULL - fooBarFrotz value3 - key1 value1 - key2 value2 - EOF - - sort <actual.raw >actual && - test_cmp expect actual -' - -test_expect_success 'iterate (case insensitive)' ' - test-tool hashmap ignorecase >actual.raw <<-\EOF && - put key1 value1 - put key2 value2 - put fooBarFrotz value3 - iterate - EOF - - cat >expect <<-\EOF && - NULL - NULL - NULL - fooBarFrotz value3 - key1 value1 - key2 value2 - EOF - - sort <actual.raw >actual && - test_cmp expect actual -' - -test_expect_success 'grow / shrink' ' - - rm -f in && - rm -f expect && - for n in $(test_seq 51) - do - echo put key$n value$n >> in && - echo NULL >> expect || return 1 - done && - echo size >> in && - echo 64 51 >> expect && - echo put key52 value52 >> in && - echo NULL >> expect && - echo size >> in && - echo 256 52 >> expect && - for n in $(test_seq 12) - do - echo remove key$n >> in && - echo value$n >> expect || return 1 - done && - echo size >> in && - echo 256 40 >> expect && - echo remove key40 >> in && - echo value40 >> expect && - echo size >> in && - echo 64 39 >> expect && - test-tool hashmap <in >out && - test_cmp expect out - -' - -test_expect_success 'string interning' ' - -test_hashmap "intern value1 -intern Value1 -intern value2 -intern value2 -" "value1 -Value1 -value2 -value2" - -' - -test_done diff --git a/t/t0013-sha1dc.sh b/t/t0013-sha1dc.sh index 08814173cb..ce3d81227a 100755 --- a/t/t0013-sha1dc.sh +++ b/t/t0013-sha1dc.sh @@ -2,7 +2,6 @@ test_description='test sha1 collision detection' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh TEST_DATA="$TEST_DIRECTORY/t0013" diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh index f3a16859cc..32fe848179 100755 --- a/t/t0017-env-helper.sh +++ b/t/t0017-env-helper.sh @@ -2,7 +2,6 @@ test_description='test test-tool env-helper' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh index 29306b367c..f68e08d0b1 100755 --- a/t/t0018-advice.sh +++ b/t/t0018-advice.sh @@ -5,13 +5,12 @@ test_description='Test advise_if_enabled functionality' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=trunk export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'advice should be printed when config variable is unset' ' cat >expect <<-\EOF && hint: This is a piece of advice - hint: Disable this message with "git config advice.nestedTag false" + hint: Disable this message with "git config set advice.nestedTag false" EOF test-tool advise "This is a piece of advice" 2>actual && test_cmp expect actual @@ -96,7 +95,6 @@ test_expect_success 'advice should be printed when GIT_ADVICE is set to true' ' >README && GIT_ADVICE=true git status ) >actual && - cat actual > /tmp/actual && test_cmp expect actual ' diff --git a/t/t0019-json-writer.sh b/t/t0019-json-writer.sh index 19a730c29e..3a4e1cc7e3 100755 --- a/t/t0019-json-writer.sh +++ b/t/t0019-json-writer.sh @@ -2,7 +2,6 @@ test_description='test json-writer JSON generation' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'unit test of json-writer routines' ' diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 81946e87cc..fd1cae09ed 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -5,7 +5,6 @@ test_description='CRLF conversion' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh has_cr() { diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index eeb2714d9d..3f6433d304 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -5,7 +5,6 @@ test_description='blob conversion via gitattributes' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -1116,11 +1115,11 @@ do test_delayed_checkout_progress test_terminal git checkout $opt ' - test_expect_success PERL "delayed checkout ommits progress on non-tty ($mode checkout)" ' + test_expect_success PERL "delayed checkout omits progress on non-tty ($mode checkout)" ' test_delayed_checkout_progress ! git checkout $opt ' - test_expect_success PERL,TTY "delayed checkout ommits progress with --quiet ($mode checkout)" ' + test_expect_success PERL,TTY "delayed checkout omits progress with --quiet ($mode checkout)" ' test_delayed_checkout_progress ! test_terminal git checkout --quiet $opt ' diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh index 9fe9891251..9bd863a970 100755 --- a/t/t0022-crlf-rename.sh +++ b/t/t0022-crlf-rename.sh @@ -2,7 +2,6 @@ test_description='ignore CR in CRLF sequence while computing similiarity' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh index 575805513a..f9bbb91f64 100755 --- a/t/t0023-crlf-am.sh +++ b/t/t0023-crlf-am.sh @@ -2,7 +2,6 @@ test_description='Test am with auto.crlf' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >patchfile <<\EOF diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh index a7f4de4a43..44958cb2c2 100755 --- a/t/t0024-crlf-archive.sh +++ b/t/t0024-crlf-archive.sh @@ -2,7 +2,6 @@ test_description='respect crlf in git archive' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t0025-crlf-renormalize.sh b/t/t0025-crlf-renormalize.sh index f7202c192e..2e28feb69c 100755 --- a/t/t0025-crlf-renormalize.sh +++ b/t/t0025-crlf-renormalize.sh @@ -2,7 +2,6 @@ test_description='CRLF renormalization' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t0026-eol-config.sh b/t/t0026-eol-config.sh index f426a185bb..493b01a0e7 100755 --- a/t/t0026-eol-config.sh +++ b/t/t0026-eol-config.sh @@ -2,7 +2,6 @@ test_description='CRLF conversion' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh has_cr() { diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 2f57c8669c..49dbf09da7 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -2,7 +2,6 @@ test_description='CRLF conversion all combinations' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh compare_files () { diff --git a/t/t0028-working-tree-encoding.sh b/t/t0028-working-tree-encoding.sh index ad151a3467..50b3b4649b 100755 --- a/t/t0028-working-tree-encoding.sh +++ b/t/t0028-working-tree-encoding.sh @@ -5,13 +5,18 @@ test_description='working-tree-encoding conversion via gitattributes' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh . "$TEST_DIRECTORY/lib-encoding.sh" GIT_TRACE_WORKING_TREE_ENCODING=1 && export GIT_TRACE_WORKING_TREE_ENCODING +if ! test_have_prereq ICONV +then + skip_all='skipping working tree encoding tests; iconv not available' + test_done +fi + test_expect_success 'setup test files' ' git config core.eol lf && diff --git a/t/t0029-core-unsetenvvars.sh b/t/t0029-core-unsetenvvars.sh index 4e8e90dd98..baa1b7e85b 100755 --- a/t/t0029-core-unsetenvvars.sh +++ b/t/t0029-core-unsetenvvars.sh @@ -2,7 +2,6 @@ test_description='test the Windows-only core.unsetenvvars setting' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq MINGW diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh index f10f42ff1e..43155f6bd8 100755 --- a/t/t0030-stripspace.sh +++ b/t/t0030-stripspace.sh @@ -5,7 +5,6 @@ test_description='git stripspace' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh t40='A quick brown fox jumps over the lazy do' diff --git a/t/t0032-reftable-unittest.sh b/t/t0032-reftable-unittest.sh deleted file mode 100755 index 471cb37ac2..0000000000 --- a/t/t0032-reftable-unittest.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2020 Google LLC -# - -test_description='reftable unittests' - -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -test_expect_success 'unittests' ' - TMPDIR=$(pwd) && export TMPDIR && - test-tool reftable -' - -test_done diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh index 5fe61f1291..e103fe7109 100755 --- a/t/t0033-safe-directory.sh +++ b/t/t0033-safe-directory.sh @@ -2,7 +2,6 @@ test_description='verify safe.directory checks' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh GIT_TEST_ASSUME_DIFFERENT_OWNER=1 @@ -119,4 +118,182 @@ test_expect_success 'local clone of unowned repo accepted in safe directory' ' test_path_is_dir target ' +test_expect_success SYMLINKS 'checked paths are normalized' ' + test_when_finished "rm -rf repository; rm -f repo" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + git init repository && + ln -s repository repo && + ( + cd repository && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "$(pwd)/repository" + ) && + git -C repository for-each-ref && + git -C repository/ for-each-ref && + git -C repo for-each-ref && + git -C repo/ for-each-ref && + test_must_fail git -C repository/.git for-each-ref && + test_must_fail git -C repository/.git/ for-each-ref && + test_must_fail git -C repo/.git for-each-ref && + test_must_fail git -C repo/.git/ for-each-ref +' + +test_expect_success SYMLINKS 'checked leading paths are normalized' ' + test_when_finished "rm -rf repository; rm -f repo" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + mkdir -p repository && + git init repository/s && + ln -s repository repo && + ( + cd repository/s && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "$(pwd)/repository/*" + ) && + git -C repository/s for-each-ref && + git -C repository/s/ for-each-ref && + git -C repo/s for-each-ref && + git -C repo/s/ for-each-ref && + git -C repository/s/.git for-each-ref && + git -C repository/s/.git/ for-each-ref && + git -C repo/s/.git for-each-ref && + git -C repo/s/.git/ for-each-ref +' + +test_expect_success SYMLINKS 'configured paths are normalized' ' + test_when_finished "rm -rf repository; rm -f repo" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + git init repository && + ln -s repository repo && + ( + cd repository && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "$(pwd)/repo" + ) && + git -C repository for-each-ref && + git -C repository/ for-each-ref && + git -C repo for-each-ref && + git -C repo/ for-each-ref && + test_must_fail git -C repository/.git for-each-ref && + test_must_fail git -C repository/.git/ for-each-ref && + test_must_fail git -C repo/.git for-each-ref && + test_must_fail git -C repo/.git/ for-each-ref +' + +test_expect_success SYMLINKS 'configured leading paths are normalized' ' + test_when_finished "rm -rf repository; rm -f repo" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + mkdir -p repository && + git init repository/s && + ln -s repository repo && + ( + cd repository/s && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "$(pwd)/repo/*" + ) && + git -C repository/s for-each-ref && + git -C repository/s/ for-each-ref && + git -C repository/s/.git for-each-ref && + git -C repository/s/.git/ for-each-ref && + git -C repo/s for-each-ref && + git -C repo/s/ for-each-ref && + git -C repo/s/.git for-each-ref && + git -C repo/s/.git/ for-each-ref +' + +test_expect_success 'safe.directory set to a dot' ' + test_when_finished "rm -rf repository" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + mkdir -p repository/subdir && + git init repository && + ( + cd repository && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "." + ) && + git -C repository for-each-ref && + git -C repository/ for-each-ref && + git -C repository/.git for-each-ref && + git -C repository/.git/ for-each-ref && + + # What is allowed is repository/subdir but the repository + # path is repository. + test_must_fail git -C repository/subdir for-each-ref && + + # Likewise, repository .git/refs is allowed with "." but + # repository/.git that is accessed is not allowed. + test_must_fail git -C repository/.git/refs for-each-ref +' + +test_expect_success 'safe.directory set to asterisk' ' + test_when_finished "rm -rf repository" && + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global --unset-all safe.directory + ) && + mkdir -p repository/subdir && + git init repository && + ( + cd repository && + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + test_commit sample + ) && + + ( + sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config --global safe.directory "*" + ) && + # these are trivial + git -C repository for-each-ref && + git -C repository/ for-each-ref && + git -C repository/.git for-each-ref && + git -C repository/.git/ for-each-ref && + + # With "*", everything is allowed, and the repository is + # discovered, which is different behaviour from "." above. + git -C repository/subdir for-each-ref && + + # Likewise. + git -C repository/.git/refs for-each-ref +' + test_done diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh index d3cb2a1cb9..ae7ef092ab 100755 --- a/t/t0035-safe-bare-repository.sh +++ b/t/t0035-safe-bare-repository.sh @@ -2,7 +2,6 @@ test_description='verify safe.bareRepository checks' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pwd="$(pwd)" diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 45a773642f..2fe3522305 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -5,7 +5,6 @@ test_description='our own option parser' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expect <<\EOF diff --git a/t/t0041-usage.sh b/t/t0041-usage.sh index 1464294bd1..a0f6f134c7 100755 --- a/t/t0041-usage.sh +++ b/t/t0041-usage.sh @@ -5,7 +5,6 @@ test_description='Test commands behavior when given invalid argument value' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ' ' diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh index 325eb1c3cd..5c9dc90d0b 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -5,7 +5,6 @@ test_description='Various filesystem issues' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh auml=$(printf '\303\244') diff --git a/t/t0052-simple-ipc.sh b/t/t0052-simple-ipc.sh index 1a36a53574..ff98be31a5 100755 --- a/t/t0052-simple-ipc.sh +++ b/t/t0052-simple-ipc.sh @@ -2,7 +2,6 @@ test_description='simple command server' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test-tool simple-ipc SUPPORTS_SIMPLE_IPC || { diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh index c3eb1158ef..d0740038b8 100755 --- a/t/t0055-beyond-symlinks.sh +++ b/t/t0055-beyond-symlinks.sh @@ -2,7 +2,6 @@ test_description='update-index and add refuse to add beyond symlinks' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success SYMLINKS setup ' diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh index 752aa8c945..2630e756da 100755 --- a/t/t0056-git-C.sh +++ b/t/t0056-git-C.sh @@ -2,7 +2,6 @@ test_description='"-C <path>" option and its effects on other path-related options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success '"git -C <path>" runs git from the directory <path>' ' diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 0afa3d0d31..dbb2e73bcd 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -5,7 +5,6 @@ test_description='Test various path utilities' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh norm_path() { diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index 20986b693c..76d4936a87 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -5,7 +5,6 @@ test_description='Test run command' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >hello-script <<-EOF diff --git a/t/t0062-revision-walking.sh b/t/t0062-revision-walking.sh index b9480c8178..8e215867b8 100755 --- a/t/t0062-revision-walking.sh +++ b/t/t0062-revision-walking.sh @@ -5,7 +5,6 @@ test_description='Test revision walking api' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >run_twice_expected <<-EOF diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh index 1fee6d9010..aac63ba506 100755 --- a/t/t0063-string-list.sh +++ b/t/t0063-string-list.sh @@ -5,7 +5,6 @@ test_description='Test string list functionality' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_split () { diff --git a/t/t0064-oid-array.sh b/t/t0064-oid-array.sh deleted file mode 100755 index de74b692d0..0000000000 --- a/t/t0064-oid-array.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/sh - -test_description='basic tests for the oid array implementation' - -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -echoid () { - prefix="${1:+$1 }" - shift - while test $# -gt 0 - do - echo "$prefix$ZERO_OID" | sed -e "s/00/$1/g" - shift - done -} - -test_expect_success 'without repository' ' - cat >expect <<-EOF && - 4444444444444444444444444444444444444444 - 5555555555555555555555555555555555555555 - 8888888888888888888888888888888888888888 - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - EOF - cat >input <<-EOF && - append 4444444444444444444444444444444444444444 - append 5555555555555555555555555555555555555555 - append 8888888888888888888888888888888888888888 - append aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - for_each_unique - EOF - nongit test-tool oid-array <input >actual && - test_cmp expect actual -' - -test_expect_success 'ordered enumeration' ' - echoid "" 44 55 88 aa >expect && - { - echoid append 88 44 aa 55 && - echo for_each_unique - } | test-tool oid-array >actual && - test_cmp expect actual -' - -test_expect_success 'ordered enumeration with duplicate suppression' ' - echoid "" 44 55 88 aa >expect && - { - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echo for_each_unique - } | test-tool oid-array >actual && - test_cmp expect actual -' - -test_expect_success 'lookup' ' - { - echoid append 88 44 aa 55 && - echoid lookup 55 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -eq 1 -' - -test_expect_success 'lookup non-existing entry' ' - { - echoid append 88 44 aa 55 && - echoid lookup 33 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -lt 0 -' - -test_expect_success 'lookup with duplicates' ' - { - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echoid lookup 55 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -ge 3 && - test "$n" -le 5 -' - -test_expect_success 'lookup non-existing entry with duplicates' ' - { - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echoid append 88 44 aa 55 && - echoid lookup 66 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -lt 0 -' - -test_expect_success 'lookup with almost duplicate values' ' - # n-1 5s - root=$(echoid "" 55) && - root=${root%5} && - { - id1="${root}5" && - id2="${root}f" && - echo "append $id1" && - echo "append $id2" && - echoid lookup 55 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -eq 0 -' - -test_expect_success 'lookup with single duplicate value' ' - { - echoid append 55 55 && - echoid lookup 55 - } | test-tool oid-array >actual && - n=$(cat actual) && - test "$n" -ge 0 && - test "$n" -le 1 -' - -test_done diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh index 7d0a0da8c0..df3e9f5fa5 100755 --- a/t/t0066-dir-iterator.sh +++ b/t/t0066-dir-iterator.sh @@ -2,7 +2,6 @@ test_description='Test the dir-iterator functionality' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t0067-parse_pathspec_file.sh b/t/t0067-parse_pathspec_file.sh index 0188d0423a..7bab49f361 100755 --- a/t/t0067-parse_pathspec_file.sh +++ b/t/t0067-parse_pathspec_file.sh @@ -2,7 +2,6 @@ test_description='Test parse_pathspec_file()' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'one item from stdin' ' diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh index 95019e01ed..f2f3e50031 100755 --- a/t/t0068-for-each-repo.sh +++ b/t/t0068-for-each-repo.sh @@ -2,7 +2,6 @@ test_description='git for-each-repo builtin' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'run based on configured value' ' diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh index 0ecec2ba71..6b9dcf984b 100755 --- a/t/t0070-fundamental.sh +++ b/t/t0070-fundamental.sh @@ -6,7 +6,6 @@ test_description='check that the most basic functions work Verify wrappers and compatibility functions. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'mktemp to nonexistent directory prints filename' ' diff --git a/t/t0071-sort.sh b/t/t0071-sort.sh index ba8ad1d1ca..2236a7e956 100755 --- a/t/t0071-sort.sh +++ b/t/t0071-sort.sh @@ -2,7 +2,6 @@ test_description='verify sort functions' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'DEFINE_LIST_SORT_DEBUG' ' diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh index 7bbb065d58..3db10f095c 100755 --- a/t/t0080-unit-test-output.sh +++ b/t/t0080-unit-test-output.sh @@ -2,26 +2,26 @@ test_description='Test the output of the unit test framework' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -test_expect_success 'TAP output from unit tests' ' +test_expect_success 'TAP output from unit tests' - <<\EOT cat >expect <<-EOF && + # BUG: check outside of test at t/helper/test-example-tap.c:75 ok 1 - passing test ok 2 - passing test and assertion return 1 - # check "1 == 2" failed at t/helper/test-example-tap.c:77 + # check "1 == 2" failed at t/helper/test-example-tap.c:79 # left: 1 # right: 2 not ok 3 - failing test ok 4 - failing test and assertion return 0 not ok 5 - passing TEST_TODO() # TODO ok 6 - passing TEST_TODO() returns 1 - # todo check ${SQ}check(x)${SQ} succeeded at t/helper/test-example-tap.c:26 + # todo check 'check(x)' succeeded at t/helper/test-example-tap.c:26 not ok 7 - failing TEST_TODO() ok 8 - failing TEST_TODO() returns 0 # check "0" failed at t/helper/test-example-tap.c:31 # skipping test - missing prerequisite - # skipping check ${SQ}1${SQ} at t/helper/test-example-tap.c:33 + # skipping check '1' at t/helper/test-example-tap.c:33 ok 9 - test_skip() # SKIP ok 10 - skipped test returns 1 # skipping test - missing prerequisite @@ -39,21 +39,54 @@ test_expect_success 'TAP output from unit tests' ' # check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:63 # left: "NULL" # right: NULL - # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/helper/test-example-tap.c:64 - # left: ${SQ}a${SQ} - # right: ${SQ}\012${SQ} - # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/helper/test-example-tap.c:65 - # left: ${SQ}\\\\${SQ} - # right: ${SQ}\\${SQ}${SQ} + # check "'a' == '\n'" failed at t/helper/test-example-tap.c:64 + # left: 'a' + # right: '\012' + # check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:65 + # left: '\\\\' + # right: '\\'' not ok 17 - messages from failing string and char comparison - # BUG: test has no checks at t/helper/test-example-tap.c:92 + # BUG: test has no checks at t/helper/test-example-tap.c:94 not ok 18 - test with no checks ok 19 - test with no checks returns 0 - 1..19 + ok 20 - if_test passing test + # check "1 == 2" failed at t/helper/test-example-tap.c:100 + # left: 1 + # right: 2 + not ok 21 - if_test failing test + not ok 22 - if_test passing TEST_TODO() # TODO + # todo check 'check(1)' succeeded at t/helper/test-example-tap.c:104 + not ok 23 - if_test failing TEST_TODO() + # check "0" failed at t/helper/test-example-tap.c:106 + # skipping test - missing prerequisite + # skipping check '1' at t/helper/test-example-tap.c:108 + ok 24 - if_test test_skip() # SKIP + # skipping test - missing prerequisite + ok 25 - if_test test_skip() inside TEST_TODO() # SKIP + # check "0" failed at t/helper/test-example-tap.c:113 + not ok 26 - if_test TEST_TODO() after failing check + # check "0" failed at t/helper/test-example-tap.c:119 + not ok 27 - if_test failing check after TEST_TODO() + # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:122 + # left: "\011hello\\\\" + # right: "there\"\012" + # check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:123 + # left: "NULL" + # right: NULL + # check "'a' == '\n'" failed at t/helper/test-example-tap.c:124 + # left: 'a' + # right: '\012' + # check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:125 + # left: '\\\\' + # right: '\\'' + not ok 28 - if_test messages from failing string and char comparison + # BUG: test has no checks at t/helper/test-example-tap.c:127 + not ok 29 - if_test test with no checks + 1..29 EOF ! test-tool example-tap >actual && test_cmp expect actual -' +EOT test_done diff --git a/t/t0081-find-pack.sh b/t/t0081-find-pack.sh index 67b11216a3..5a628bf735 100755 --- a/t/t0081-find-pack.sh +++ b/t/t0081-find-pack.sh @@ -2,7 +2,6 @@ test_description='test `test-tool find-pack`' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh index d8e2fc42e1..ab80c9ef13 100755 --- a/t/t0090-cache-tree.sh +++ b/t/t0090-cache-tree.sh @@ -6,7 +6,6 @@ Tests whether various commands properly update and/or rewrite the cache-tree extension. " -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cmp_cache_tree () { diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh index fca39048fe..e11d819b62 100755 --- a/t/t0091-bugreport.sh +++ b/t/t0091-bugreport.sh @@ -2,7 +2,6 @@ test_description='git bugreport' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create a report' ' diff --git a/t/t0092-diagnose.sh b/t/t0092-diagnose.sh index 133e5747d6..6cabd6e67b 100755 --- a/t/t0092-diagnose.sh +++ b/t/t0092-diagnose.sh @@ -2,7 +2,6 @@ test_description='git diagnose' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success UNZIP 'creates diagnostics zip archive' ' diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh index c8d84ab606..8f0c3b7325 100755 --- a/t/t0095-bloom.sh +++ b/t/t0095-bloom.sh @@ -2,7 +2,6 @@ test_description='Testing the various Bloom filter computations in bloom.c' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'compute unseeded murmur3 hash for empty string' ' @@ -77,7 +76,7 @@ test_expect_success 'compute bloom key for test string 2' ' test_cmp expect actual ' -test_expect_success !SANITIZE_LEAK 'get bloom filters for commit with no changes' ' +test_expect_success 'get bloom filters for commit with no changes' ' git init && git commit --allow-empty -m "c0" && cat >expect <<-\EOF && diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh index 70a3223f21..dd5d9b4e5e 100755 --- a/t/t0100-previous.sh +++ b/t/t0100-previous.sh @@ -5,7 +5,6 @@ test_description='previous branch syntax @{-n}' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'branch -d @{-1}' ' diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh index 878aadd64c..023b4c6f0b 100755 --- a/t/t0101-at-syntax.sh +++ b/t/t0101-at-syntax.sh @@ -2,7 +2,6 @@ test_description='various @{whatever} syntax tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t0110-urlmatch-normalization.sh b/t/t0110-urlmatch-normalization.sh deleted file mode 100755 index 12d817fbd3..0000000000 --- a/t/t0110-urlmatch-normalization.sh +++ /dev/null @@ -1,182 +0,0 @@ -#!/bin/sh - -test_description='urlmatch URL normalization' - -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -# The base name of the test url files -tu="$TEST_DIRECTORY/t0110/url" - -# Note that only file: URLs should be allowed without a host - -test_expect_success 'url scheme' ' - ! test-tool urlmatch-normalization "" && - ! test-tool urlmatch-normalization "_" && - ! test-tool urlmatch-normalization "scheme" && - ! test-tool urlmatch-normalization "scheme:" && - ! test-tool urlmatch-normalization "scheme:/" && - ! test-tool urlmatch-normalization "scheme://" && - ! test-tool urlmatch-normalization "file" && - ! test-tool urlmatch-normalization "file:" && - ! test-tool urlmatch-normalization "file:/" && - test-tool urlmatch-normalization "file://" && - ! test-tool urlmatch-normalization "://acme.co" && - ! test-tool urlmatch-normalization "x_test://acme.co" && - ! test-tool urlmatch-normalization "-test://acme.co" && - ! test-tool urlmatch-normalization "0test://acme.co" && - ! test-tool urlmatch-normalization "+test://acme.co" && - ! test-tool urlmatch-normalization ".test://acme.co" && - ! test-tool urlmatch-normalization "schem%6e://" && - test-tool urlmatch-normalization "x-Test+v1.0://acme.co" && - test "$(test-tool urlmatch-normalization -p "AbCdeF://x.Y")" = "abcdef://x.y/" -' - -test_expect_success 'url authority' ' - ! test-tool urlmatch-normalization "scheme://user:pass@" && - ! test-tool urlmatch-normalization "scheme://?" && - ! test-tool urlmatch-normalization "scheme://#" && - ! test-tool urlmatch-normalization "scheme:///" && - ! test-tool urlmatch-normalization "scheme://:" && - ! test-tool urlmatch-normalization "scheme://:555" && - test-tool urlmatch-normalization "file://user:pass@" && - test-tool urlmatch-normalization "file://?" && - test-tool urlmatch-normalization "file://#" && - test-tool urlmatch-normalization "file:///" && - test-tool urlmatch-normalization "file://:" && - ! test-tool urlmatch-normalization "file://:555" && - test-tool urlmatch-normalization "scheme://user:pass@host" && - test-tool urlmatch-normalization "scheme://@host" && - test-tool urlmatch-normalization "scheme://%00@host" && - ! test-tool urlmatch-normalization "scheme://%%@host" && - test-tool urlmatch-normalization "scheme://host_" && - test-tool urlmatch-normalization "scheme://user:pass@host/" && - test-tool urlmatch-normalization "scheme://@host/" && - test-tool urlmatch-normalization "scheme://host/" && - test-tool urlmatch-normalization "scheme://host?x" && - test-tool urlmatch-normalization "scheme://host#x" && - test-tool urlmatch-normalization "scheme://host/@" && - test-tool urlmatch-normalization "scheme://host?@x" && - test-tool urlmatch-normalization "scheme://host#@x" && - test-tool urlmatch-normalization "scheme://[::1]" && - test-tool urlmatch-normalization "scheme://[::1]/" && - ! test-tool urlmatch-normalization "scheme://hos%41/" && - test-tool urlmatch-normalization "scheme://[invalid....:/" && - test-tool urlmatch-normalization "scheme://invalid....:]/" && - ! test-tool urlmatch-normalization "scheme://invalid....:[/" && - ! test-tool urlmatch-normalization "scheme://invalid....:[" -' - -test_expect_success 'url port checks' ' - test-tool urlmatch-normalization "xyz://q@some.host:" && - test-tool urlmatch-normalization "xyz://q@some.host:456/" && - ! test-tool urlmatch-normalization "xyz://q@some.host:0" && - ! test-tool urlmatch-normalization "xyz://q@some.host:0000000" && - test-tool urlmatch-normalization "xyz://q@some.host:0000001?" && - test-tool urlmatch-normalization "xyz://q@some.host:065535#" && - test-tool urlmatch-normalization "xyz://q@some.host:65535" && - ! test-tool urlmatch-normalization "xyz://q@some.host:65536" && - ! test-tool urlmatch-normalization "xyz://q@some.host:99999" && - ! test-tool urlmatch-normalization "xyz://q@some.host:100000" && - ! test-tool urlmatch-normalization "xyz://q@some.host:100001" && - test-tool urlmatch-normalization "http://q@some.host:80" && - test-tool urlmatch-normalization "https://q@some.host:443" && - test-tool urlmatch-normalization "http://q@some.host:80/" && - test-tool urlmatch-normalization "https://q@some.host:443?" && - ! test-tool urlmatch-normalization "http://q@:8008" && - ! test-tool urlmatch-normalization "http://:8080" && - ! test-tool urlmatch-normalization "http://:" && - test-tool urlmatch-normalization "xyz://q@some.host:456/" && - test-tool urlmatch-normalization "xyz://[::1]:456/" && - test-tool urlmatch-normalization "xyz://[::1]:/" && - ! test-tool urlmatch-normalization "xyz://[::1]:000/" && - ! test-tool urlmatch-normalization "xyz://[::1]:0%300/" && - ! test-tool urlmatch-normalization "xyz://[::1]:0x80/" && - ! test-tool urlmatch-normalization "xyz://[::1]:4294967297/" && - ! test-tool urlmatch-normalization "xyz://[::1]:030f/" -' - -test_expect_success 'url port normalization' ' - test "$(test-tool urlmatch-normalization -p "http://x:800")" = "http://x:800/" && - test "$(test-tool urlmatch-normalization -p "http://x:0800")" = "http://x:800/" && - test "$(test-tool urlmatch-normalization -p "http://x:00000800")" = "http://x:800/" && - test "$(test-tool urlmatch-normalization -p "http://x:065535")" = "http://x:65535/" && - test "$(test-tool urlmatch-normalization -p "http://x:1")" = "http://x:1/" && - test "$(test-tool urlmatch-normalization -p "http://x:80")" = "http://x/" && - test "$(test-tool urlmatch-normalization -p "http://x:080")" = "http://x/" && - test "$(test-tool urlmatch-normalization -p "http://x:000000080")" = "http://x/" && - test "$(test-tool urlmatch-normalization -p "https://x:443")" = "https://x/" && - test "$(test-tool urlmatch-normalization -p "https://x:0443")" = "https://x/" && - test "$(test-tool urlmatch-normalization -p "https://x:000000443")" = "https://x/" -' - -test_expect_success 'url general escapes' ' - ! test-tool urlmatch-normalization "http://x.y?%fg" && - test "$(test-tool urlmatch-normalization -p "X://W/%7e%41^%3a")" = "x://w/~A%5E%3A" && - test "$(test-tool urlmatch-normalization -p "X://W/:/?#[]@")" = "x://w/:/?#[]@" && - test "$(test-tool urlmatch-normalization -p "X://W/$&()*+,;=")" = "x://w/$&()*+,;=" && - test "$(test-tool urlmatch-normalization -p "X://W/'\''")" = "x://w/'\''" && - test "$(test-tool urlmatch-normalization -p "X://W?'\!'")" = "x://w/?'\!'" -' - -test_expect_success !MINGW 'url high-bit escapes' ' - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-1")")" = "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-2")")" = "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-3")")" = "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-4")")" = "x://q/%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-5")")" = "x://q/%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-6")")" = "x://q/%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-7")")" = "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-8")")" = "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-9")")" = "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" && - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF" -' - -test_expect_success 'url utf-8 escapes' ' - test "$(test-tool urlmatch-normalization -p "$(cat "$tu-11")")" = "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD" -' - -test_expect_success 'url username/password escapes' ' - test "$(test-tool urlmatch-normalization -p "x://%41%62(^):%70+d@foo")" = "x://Ab(%5E):p+d@foo/" -' - -test_expect_success 'url normalized lengths' ' - test "$(test-tool urlmatch-normalization -l "Http://%4d%65:%4d^%70@The.Host")" = 25 && - test "$(test-tool urlmatch-normalization -l "http://%41:%42@x.y/%61/")" = 17 && - test "$(test-tool urlmatch-normalization -l "http://@x.y/^")" = 15 -' - -test_expect_success 'url . and .. segments' ' - test "$(test-tool urlmatch-normalization -p "x://y/.")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/./")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/a/.")" = "x://y/a" && - test "$(test-tool urlmatch-normalization -p "x://y/a/./")" = "x://y/a/" && - test "$(test-tool urlmatch-normalization -p "x://y/.?")" = "x://y/?" && - test "$(test-tool urlmatch-normalization -p "x://y/./?")" = "x://y/?" && - test "$(test-tool urlmatch-normalization -p "x://y/a/.?")" = "x://y/a?" && - test "$(test-tool urlmatch-normalization -p "x://y/a/./?")" = "x://y/a/?" && - test "$(test-tool urlmatch-normalization -p "x://y/a/./b/.././../c")" = "x://y/c" && - test "$(test-tool urlmatch-normalization -p "x://y/a/./b/../.././c/")" = "x://y/c/" && - test "$(test-tool urlmatch-normalization -p "x://y/a/./b/.././../c/././.././.")" = "x://y/" && - ! test-tool urlmatch-normalization "x://y/a/./b/.././../c/././.././.." && - test "$(test-tool urlmatch-normalization -p "x://y/a/./?/././..")" = "x://y/a/?/././.." && - test "$(test-tool urlmatch-normalization -p "x://y/%2e/")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/%2E/")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/a/%2e./")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/b/.%2E/")" = "x://y/" && - test "$(test-tool urlmatch-normalization -p "x://y/c/%2e%2E/")" = "x://y/" -' - -# http://@foo specifies an empty user name but does not specify a password -# http://foo specifies neither a user name nor a password -# So they should not be equivalent -test_expect_success 'url equivalents' ' - test-tool urlmatch-normalization "httP://x" "Http://X/" && - test-tool urlmatch-normalization "Http://%4d%65:%4d^%70@The.Host" "hTTP://Me:%4D^p@the.HOST:80/" && - ! test-tool urlmatch-normalization "https://@x.y/^" "httpS://x.y:443/^" && - test-tool urlmatch-normalization "https://@x.y/^" "httpS://@x.y:0443/^" && - test-tool urlmatch-normalization "https://@x.y/^/../abc" "httpS://@x.y:0443/abc" && - test-tool urlmatch-normalization "https://@x.y/^/.." "httpS://@x.y:0443/" -' - -test_done diff --git a/t/t0110/README b/t/t0110/README deleted file mode 100644 index ad4a50ecd8..0000000000 --- a/t/t0110/README +++ /dev/null @@ -1,9 +0,0 @@ -The url data files in this directory contain URLs with characters -in the range 0x01-0x1f and 0x7f-0xff to test the proper normalization -of unprintable characters. - -A select few characters in the 0x01-0x1f range are skipped to help -avoid problems running the test itself. - -The urls are in test files in this directory rather than being -embedded in the test script for portability. diff --git a/t/t0110/url-1 b/t/t0110/url-1 deleted file mode 100644 index 519019c5ce..0000000000 --- a/t/t0110/url-1 +++ /dev/null @@ -1 +0,0 @@ -x://q/ diff --git a/t/t0110/url-10 b/t/t0110/url-10 deleted file mode 100644 index b9965de6a5..0000000000 --- a/t/t0110/url-10 +++ /dev/null @@ -1 +0,0 @@ -x://q/ðñòóôõö÷øùúûüýþÿ diff --git a/t/t0110/url-11 b/t/t0110/url-11 deleted file mode 100644 index f0a50f1009..0000000000 --- a/t/t0110/url-11 +++ /dev/null @@ -1 +0,0 @@ -x://q/Â€ß¿à €ï¿½ð€€ð¯¿½ diff --git a/t/t0110/url-2 b/t/t0110/url-2 deleted file mode 100644 index 43334b05b2..0000000000 --- a/t/t0110/url-2 +++ /dev/null @@ -1 +0,0 @@ -x://q/ diff --git a/t/t0110/url-3 b/t/t0110/url-3 deleted file mode 100644 index 7378c7bec2..0000000000 --- a/t/t0110/url-3 +++ /dev/null @@ -1 +0,0 @@ -x://q/€‚ƒ„…†‡ˆ‰Š‹ŒŽ diff --git a/t/t0110/url-4 b/t/t0110/url-4 deleted file mode 100644 index 220b198c97..0000000000 --- a/t/t0110/url-4 +++ /dev/null @@ -1 +0,0 @@ -x://q/‘’“”•–—˜™š›œžŸ diff --git a/t/t0110/url-5 b/t/t0110/url-5 deleted file mode 100644 index 1ccd927779..0000000000 --- a/t/t0110/url-5 +++ /dev/null @@ -1 +0,0 @@ -x://q/ ¡¢£¤¥¦§¨©ª«¬®¯ diff --git a/t/t0110/url-6 b/t/t0110/url-6 deleted file mode 100644 index e8283aac6d..0000000000 --- a/t/t0110/url-6 +++ /dev/null @@ -1 +0,0 @@ -x://q/°±²³´µ¶·¸¹º»¼½¾¿ diff --git a/t/t0110/url-7 b/t/t0110/url-7 deleted file mode 100644 index fa7c10b615..0000000000 --- a/t/t0110/url-7 +++ /dev/null @@ -1 +0,0 @@ -x://q/ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ diff --git a/t/t0110/url-8 b/t/t0110/url-8 deleted file mode 100644 index 79a0ba836f..0000000000 --- a/t/t0110/url-8 +++ /dev/null @@ -1 +0,0 @@ -x://q/ÐÑÒÓÔÕÖרÙÚÛÜÝÞß diff --git a/t/t0110/url-9 b/t/t0110/url-9 deleted file mode 100644 index 8b44bec48b..0000000000 --- a/t/t0110/url-9 +++ /dev/null @@ -1 +0,0 @@ -x://q/àáâãäåæçèéêëìíîï diff --git a/t/t0200-gettext-basic.sh b/t/t0200-gettext-basic.sh index 522fb2ae69..8853d8afb9 100755 --- a/t/t0200-gettext-basic.sh +++ b/t/t0200-gettext-basic.sh @@ -5,7 +5,6 @@ test_description='Gettext support for Git' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" ' diff --git a/t/t0201-gettext-fallbacks.sh b/t/t0201-gettext-fallbacks.sh index 8724ce1052..6c74df0dc6 100755 --- a/t/t0201-gettext-fallbacks.sh +++ b/t/t0201-gettext-fallbacks.sh @@ -8,7 +8,6 @@ test_description='Gettext Shell fallbacks' GIT_INTERNAL_GETTEXT_TEST_FALLBACKS=YesPlease export GIT_INTERNAL_GETTEXT_TEST_FALLBACKS -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" ' diff --git a/t/t0202-gettext-perl.sh b/t/t0202-gettext-perl.sh index 5a6f28051b..b15cb65d5d 100755 --- a/t/t0202-gettext-perl.sh +++ b/t/t0202-gettext-perl.sh @@ -5,7 +5,6 @@ test_description='Perl gettext interface (Git::I18N)' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh . "$TEST_DIRECTORY"/lib-perl.sh skip_all_if_no_Test_More diff --git a/t/t0202/test.pl b/t/t0202/test.pl index 47d96a2a13..5085a0eda5 100755 --- a/t/t0202/test.pl +++ b/t/t0202/test.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -use 5.008001; +require v5.26; use lib (split(/:/, $ENV{GITPERLLIB})); use strict; use warnings; diff --git a/t/t0203-gettext-setlocale-sanity.sh b/t/t0203-gettext-setlocale-sanity.sh index 86cff324ff..0ce1f22eff 100755 --- a/t/t0203-gettext-setlocale-sanity.sh +++ b/t/t0203-gettext-setlocale-sanity.sh @@ -5,7 +5,6 @@ test_description="The Git C functions aren't broken by setlocale(3)" -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh test_expect_success 'git show a ISO-8859-1 commit under C locale' ' diff --git a/t/t0204-gettext-reencode-sanity.sh b/t/t0204-gettext-reencode-sanity.sh index 310a450012..28d92bb9b7 100755 --- a/t/t0204-gettext-reencode-sanity.sh +++ b/t/t0204-gettext-reencode-sanity.sh @@ -5,7 +5,6 @@ test_description="Gettext reencoding of our *.po/*.mo files works" -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh # The constants used in a tricky observation for undefined behaviour diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh index c312657a12..eff9a59dbd 100755 --- a/t/t0210-trace2-normal.sh +++ b/t/t0210-trace2-normal.sh @@ -2,7 +2,6 @@ test_description='test trace2 facility (normal target)' -TEST_PASSES_SANITIZE_LEAK=false . ./test-lib.sh # Turn off any inherited trace2 settings for this test. diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index 070fe7a5da..bac9046540 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -2,7 +2,6 @@ test_description='test trace2 facility (perf target)' -TEST_PASSES_SANITIZE_LEAK=false . ./test-lib.sh # Turn off any inherited trace2 settings for this test. @@ -337,7 +336,8 @@ test_expect_success 'expect def_params for query command' ' # remote-curl.c rather than git.c. Confirm that we get def_param # events from both layers. # -test_expect_success 'expect def_params for remote-curl and _run_dashed_' ' +test_expect_success LIBCURL \ + 'expect def_params for remote-curl and _run_dashed_' ' test_when_finished "rm prop.perf actual" && test_config_global "trace2.configParams" "cfg.prop.*" && @@ -366,7 +366,8 @@ test_expect_success 'expect def_params for remote-curl and _run_dashed_' ' # an executable built from http-fetch.c. Confirm that we get # def_param events from both layers. # -test_expect_success 'expect def_params for http-fetch and _run_dashed_' ' +test_expect_success LIBCURL \ + 'expect def_params for http-fetch and _run_dashed_' ' test_when_finished "rm prop.perf actual" && test_config_global "trace2.configParams" "cfg.prop.*" && diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh index 147643d582..1211db9f46 100755 --- a/t/t0212-trace2-event.sh +++ b/t/t0212-trace2-event.sh @@ -2,7 +2,6 @@ test_description='test trace2 facility' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Turn off any inherited trace2 settings for this test. diff --git a/t/t0212/parse_events.perl b/t/t0212/parse_events.perl index 30a9f51e9f..7146476c69 100644 --- a/t/t0212/parse_events.perl +++ b/t/t0212/parse_events.perl @@ -204,7 +204,7 @@ while (<>) { } # A series of potentially nested and threaded region and data events - # is fundamentally incompatibile with the type of summary record we + # is fundamentally incompatible with the type of summary record we # are building in this script. Since they are intended for # perf-trace-like analysis rather than a result summary, we ignore # most of them here. diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 6a76b7fdbd..17952e52d6 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -2,7 +2,6 @@ test_description='basic credential helper tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-credential.sh diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh index 5d5b64205f..dc30289f75 100755 --- a/t/t0301-credential-cache.sh +++ b/t/t0301-credential-cache.sh @@ -2,7 +2,6 @@ test_description='credential-cache tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-credential.sh diff --git a/t/t0302-credential-store.sh b/t/t0302-credential-store.sh index f83db659e2..c1cd60edd0 100755 --- a/t/t0302-credential-store.sh +++ b/t/t0302-credential-store.sh @@ -2,7 +2,6 @@ test_description='credential-store tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-credential.sh diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh index 8aadbe86c4..72ae405c3e 100755 --- a/t/t0303-credential-external.sh +++ b/t/t0303-credential-external.sh @@ -29,7 +29,6 @@ you can set GIT_TEST_CREDENTIAL_HELPER_SETUP to a sequence of shell commands. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-credential.sh diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index 2c30c86e7b..2a5bdbeeb8 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -5,8 +5,6 @@ test_description='partial clone' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh -# missing promisor objects cause repacks which write bitmaps to fail -GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 # When enabled, some commands will write commit-graphs. This causes fsck # to fail when delete_object() is called because fsck will attempt to # verify the out-of-sync commit graph. @@ -242,7 +240,7 @@ test_expect_success 'fetching of missing objects works with ref-in-want enabled' grep "fetch< fetch=.*ref-in-want" trace ' -test_expect_success 'fetching of missing objects from another promisor remote' ' +test_expect_success 'fetching from another promisor remote' ' git clone "file://$(pwd)/server" server2 && test_commit -C server2 bar && git -C server2 repack -a -d --write-bitmap-index && @@ -265,8 +263,8 @@ test_expect_success 'fetching of missing objects from another promisor remote' ' grep "$HASH2" out ' -test_expect_success 'fetching of missing objects configures a promisor remote' ' - git clone "file://$(pwd)/server" server3 && +test_expect_success 'fetching with --filter configures a promisor remote' ' + test_create_repo server3 && test_commit -C server3 baz && git -C server3 repack -a -d --write-bitmap-index && HASH3=$(git -C server3 rev-parse baz) && diff --git a/t/t0411-clone-from-partial.sh b/t/t0411-clone-from-partial.sh index 932bf2067d..196fc61784 100755 --- a/t/t0411-clone-from-partial.sh +++ b/t/t0411-clone-from-partial.sh @@ -2,7 +2,6 @@ test_description='check that local clone does not fetch from promisor remotes' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create evil repo' ' @@ -29,7 +28,6 @@ test_expect_success 'local clone must not fetch from promisor remote and execute test_must_fail git clone \ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ evil clone1 2>err && - test_grep "detected dubious ownership" err && test_grep ! "fake-upload-pack running" err && test_path_is_missing script-executed ' @@ -39,7 +37,6 @@ test_expect_success 'clone from file://... must not fetch from promisor remote a test_must_fail git clone \ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ "file://$(pwd)/evil" clone2 2>err && - test_grep "detected dubious ownership" err && test_grep ! "fake-upload-pack running" err && test_path_is_missing script-executed ' @@ -49,7 +46,6 @@ test_expect_success 'fetch from file://... must not fetch from promisor remote a test_must_fail git fetch \ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ "file://$(pwd)/evil" 2>err && - test_grep "detected dubious ownership" err && test_grep ! "fake-upload-pack running" err && test_path_is_missing script-executed ' diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh index 69917d7b84..853101b86e 100755 --- a/t/t0450-txt-doc-vs-help.sh +++ b/t/t0450-txt-doc-vs-help.sh @@ -5,7 +5,6 @@ test_description='assert (unbuilt) Documentation/*.txt 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.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup: list of builtins' ' @@ -56,14 +55,11 @@ txt_to_synopsis () { fi && b2t="$(builtin_to_txt "$builtin")" && sed -n \ - -e '/^\[verse\]$/,/^$/ { + -E '/^\[(verse|synopsis)\]$/,/^$/ { /^$/d; - /^\[verse\]$/d; - s/_//g; - s/++//g; - s/`//g; - s/{litdd}/--/g; - s/'\''\(git[ a-z-]*\)'\''/\1/g; + /^\[(verse|synopsis)\]$/d; + s/\{litdd\}/--/g; + s/'\''(git[ a-z-]*)'\''/\1/g; p; }' \ diff --git a/t/t0500-progress-display.sh b/t/t0500-progress-display.sh index 1eb3a8306b..d1a498a216 100755 --- a/t/t0500-progress-display.sh +++ b/t/t0500-progress-display.sh @@ -2,7 +2,6 @@ test_description='progress display' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh show_cr () { diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh index 20df336cc3..1e62c791d9 100755 --- a/t/t0600-reffiles-backend.sh +++ b/t/t0600-reffiles-backend.sh @@ -7,7 +7,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_DEFAULT_REF_FORMAT=files export GIT_TEST_DEFAULT_REF_FORMAT -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -271,7 +270,7 @@ test_expect_success 'setup worktree' ' # Some refs (refs/bisect/*, pseudorefs) are kept per worktree, so they should # only appear in the for-each-reflog output if it is called from the correct # worktree, which is exercised in this test. This test is poorly written for -# mulitple reasons: 1) it creates invalidly formatted log entres. 2) it uses +# multiple reasons: 1) it creates invalidly formatted log entries. 2) it uses # direct FS access for creating the reflogs. 3) PSEUDO-WT and refs/bisect/random # do not create reflogs by default, so it is not testing a realistic scenario. test_expect_success 'for_each_reflog()' ' diff --git a/t/t0601-reffiles-pack-refs.sh b/t/t0601-reffiles-pack-refs.sh index 60a544b8ee..aa7f6ecd81 100755 --- a/t/t0601-reffiles-pack-refs.sh +++ b/t/t0601-reffiles-pack-refs.sh @@ -15,7 +15,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_DEFAULT_REF_FORMAT=files export GIT_TEST_DEFAULT_REF_FORMAT -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'enable reflogs' ' @@ -161,13 +160,6 @@ test_expect_success 'test --exclude takes precedence over --include' ' git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" && test -f .git/refs/heads/dont_pack5' -test_expect_success '--auto packs and prunes refs as usual' ' - git branch auto && - test_path_is_file .git/refs/heads/auto && - git pack-refs --auto --all && - test_path_is_missing .git/refs/heads/auto -' - test_expect_success 'see if up-to-date packed refs are preserved' ' git branch q && git pack-refs --all --prune && @@ -367,14 +359,90 @@ test_expect_success 'pack-refs does not drop broken refs during deletion' ' test_cmp expect actual ' -test_expect_success 'maintenance --auto unconditionally packs loose refs' ' - git update-ref refs/heads/something HEAD && - test_path_is_file .git/refs/heads/something && - git rev-parse refs/heads/something >expect && - git maintenance run --task=pack-refs --auto && - test_path_is_missing .git/refs/heads/something && - git rev-parse refs/heads/something >actual && - test_cmp expect actual -' +for command in "git pack-refs --all --auto" "git maintenance run --task=pack-refs --auto" +do + test_expect_success "$command does not repack below 16 refs without packed-refs" ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git config set maintenance.auto false && + git commit --allow-empty --message "initial" && + + # Create 14 additional references, which brings us to + # 15 together with the default branch. + printf "create refs/heads/loose-%d HEAD\n" $(test_seq 14) >stdin && + git update-ref --stdin <stdin && + test_path_is_missing .git/packed-refs && + git pack-refs --auto --all && + test_path_is_missing .git/packed-refs && + + # Create the 16th reference, which should cause us to repack. + git update-ref refs/heads/loose-15 HEAD && + git pack-refs --auto --all && + test_path_is_file .git/packed-refs + ) + ' + + test_expect_success "$command does not repack below 16 refs with small packed-refs" ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git config set maintenance.auto false && + git commit --allow-empty --message "initial" && + + git pack-refs --all && + test_line_count = 2 .git/packed-refs && + + # Create 15 loose references. + printf "create refs/heads/loose-%d HEAD\n" $(test_seq 15) >stdin && + git update-ref --stdin <stdin && + git pack-refs --auto --all && + test_line_count = 2 .git/packed-refs && + + # Create the 16th loose reference, which should cause us to repack. + git update-ref refs/heads/loose-17 HEAD && + git pack-refs --auto --all && + test_line_count = 18 .git/packed-refs + ) + ' + + test_expect_success "$command scales with size of packed-refs" ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git config set maintenance.auto false && + git commit --allow-empty --message "initial" && + + # Create 99 packed refs. This should cause the heuristic + # to require more than the minimum amount of loose refs. + test_seq 99 | + while read i + do + printf "create refs/heads/packed-%d HEAD\n" $i || return 1 + done >stdin && + git update-ref --stdin <stdin && + git pack-refs --all && + test_line_count = 101 .git/packed-refs && + + # Create 24 loose refs, which should not yet cause us to repack. + printf "create refs/heads/loose-%d HEAD\n" $(test_seq 24) >stdin && + git update-ref --stdin <stdin && + git pack-refs --auto --all && + test_line_count = 101 .git/packed-refs && + + # Create another handful of refs to cross the border. + # Note that we explicitly do not check for strict + # boundaries here, as this also depends on the size of + # the object hash. + printf "create refs/heads/addn-%d HEAD\n" $(test_seq 10) >stdin && + git update-ref --stdin <stdin && + git pack-refs --auto --all && + test_line_count = 135 .git/packed-refs + ) + ' +done test_done diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh new file mode 100755 index 0000000000..d4a08b823b --- /dev/null +++ b/t/t0602-reffiles-fsck.sh @@ -0,0 +1,599 @@ +#!/bin/sh + +test_description='Test reffiles backend consistency check' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +GIT_TEST_DEFAULT_REF_FORMAT=files +export GIT_TEST_DEFAULT_REF_FORMAT + +. ./test-lib.sh + +test_expect_success 'ref name 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 && + + 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 && + + 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 +' + +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 $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" && + + 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/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 && + 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: '\'' + + + garbage'\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err +' + +test_expect_success 'regular ref content should be checked (aggregate)' ' + 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" && + + 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" && + + 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 && + + 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 +' + +test_expect_success 'textual symref content should be checked (aggregate)' ' + 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" && + + 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' ' + 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 && + 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" && + + 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 +' + +test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' + 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 && + 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 '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 && + 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/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 +' + +test_done diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh index b06c46999d..4618ffc108 100755 --- a/t/t0610-reftable-basics.sh +++ b/t/t0610-reftable-basics.sh @@ -10,7 +10,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_DEFAULT_REF_FORMAT=reftable export GIT_TEST_DEFAULT_REF_FORMAT -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh INVALID_OID=$(test_oid 001) @@ -423,6 +422,73 @@ test_expect_success 'ref transaction: fails gracefully when auto compaction fail ) ' +test_expect_success 'ref transaction: timeout acquiring tables.list lock' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit initial && + >.git/reftable/tables.list.lock && + test_must_fail git update-ref refs/heads/branch HEAD 2>err && + test_grep "cannot lock references" err + ) +' + +test_expect_success 'ref transaction: retry acquiring tables.list lock' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit initial && + LOCK=.git/reftable/tables.list.lock && + >$LOCK && + { + ( sleep 1 && rm -f $LOCK ) & + } && + git -c reftable.lockTimeout=5000 update-ref refs/heads/branch HEAD + ) +' + +# This test fails most of the time on Cygwin systems. The root cause is +# that Windows does not allow us to rename the "tables.list.lock" file into +# place when "tables.list" is open for reading by a concurrent process. We have +# worked around that in our MinGW-based rename emulation, but the Cygwin +# emulation seems to be insufficient. +test_expect_success !CYGWIN 'ref transaction: many concurrent writers' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + # Set a high timeout. While a couple of seconds should be + # plenty, using the address sanitizer will significantly slow + # us down here. So we are aiming way higher than you would ever + # think is necessary just to keep us from flaking. We could + # also lock indefinitely by passing -1, but that could + # potentially block CI jobs indefinitely if there was a bug + # here. + git config set reftable.lockTimeout 300000 && + test_commit --no-tag initial && + + head=$(git rev-parse HEAD) && + for i in $(test_seq 100) + do + printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" || + return 1 + done >expect && + printf "%s commit\trefs/heads/main\n" "$head" >>expect && + + for i in $(test_seq 100) + do + { git update-ref refs/heads/branch-$i HEAD& } || + return 1 + done && + + wait && + git for-each-ref --sort=v:refname >actual && + test_cmp expect actual + ) +' + test_expect_success 'pack-refs: compacts tables' ' test_when_finished "rm -rf repo" && git init repo && @@ -478,19 +544,26 @@ test_expect_success "$command: auto compaction" ' test_oid blob17_2 | git hash-object -w --stdin && - # Lock all tables write some refs. Auto-compaction will be - # unable to compact tables and thus fails gracefully, leaving - # the stack in a sub-optimal state. - ls .git/reftable/*.ref | + # Lock all tables, write some refs. Auto-compaction will be + # unable to compact tables and thus fails gracefully, + # compacting only those tables which are not locked. + ls .git/reftable/*.ref | sort | while read table do - touch "$table.lock" || exit 1 + touch "$table.lock" && + basename "$table" >>tables.expect || exit 1 done && + test_line_count = 2 .git/reftable/tables.list && git branch B && git branch C && - rm .git/reftable/*.lock && - test_line_count = 4 .git/reftable/tables.list && + # The new tables are auto-compacted, but the locked tables are + # left intact. + test_line_count = 3 .git/reftable/tables.list && + head -n 2 .git/reftable/tables.list >tables.head && + test_cmp tables.expect tables.head && + + rm .git/reftable/*.lock && git $command --auto && test_line_count = 1 .git/reftable/tables.list ) diff --git a/t/t0611-reftable-httpd.sh b/t/t0611-reftable-httpd.sh index 2805995cc8..5e05b9c1f2 100755 --- a/t/t0611-reftable-httpd.sh +++ b/t/t0611-reftable-httpd.sh @@ -2,7 +2,6 @@ test_description='reftable HTTPD tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh index 84922153ab..d0d7e80b49 100755 --- a/t/t0612-reftable-jgit-compatibility.sh +++ b/t/t0612-reftable-jgit-compatibility.sh @@ -11,7 +11,6 @@ export GIT_TEST_DEFAULT_REF_FORMAT GIT_TEST_SPLIT_INDEX=0 export GIT_TEST_SPLIT_INDEX -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq JGIT diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh index b1c6c97524..e2708e11d5 100755 --- a/t/t0613-reftable-write-options.sh +++ b/t/t0613-reftable-write-options.sh @@ -16,7 +16,6 @@ export GIT_TEST_DEFAULT_HASH GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'default write options' ' diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh index 0e8c0dfbbe..b9dd21cfb6 100755 --- a/t/t1000-read-tree-m-3way.sh +++ b/t/t1000-read-tree-m-3way.sh @@ -72,7 +72,6 @@ In addition: ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 88c524f655..4a88bb9ef0 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -21,7 +21,6 @@ In the test, these paths are used: yomin - not in H or M ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh @@ -397,7 +396,7 @@ test_expect_success 'a/b vs a, plus c/d case setup.' ' test_expect_success 'a/b vs a, plus c/d case test.' ' read_tree_u_must_succeed -u -m "$treeH" "$treeM" && - git ls-files --stage | tee >treeMcheck.out && + git ls-files --stage >treeMcheck.out && test_cmp treeM.out treeMcheck.out ' diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh index a7c2ed0d7c..df6ef53725 100755 --- a/t/t1002-read-tree-m-u-2way.sh +++ b/t/t1002-read-tree-m-u-2way.sh @@ -9,7 +9,6 @@ This is identical to t1001, but uses -u to update the work tree as well. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh index c860c08ecb..66e2bf4aec 100755 --- a/t/t1003-read-tree-prefix.sh +++ b/t/t1003-read-tree-prefix.sh @@ -6,7 +6,6 @@ test_description='git read-tree --prefix test. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index 2b9720b0fe..11bf10424f 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -5,7 +5,6 @@ test_description='read-tree -m -u checks working tree files' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh index 26be4a2b5a..6b5033d0ce 100755 --- a/t/t1005-read-tree-reset.sh +++ b/t/t1005-read-tree-reset.sh @@ -2,7 +2,6 @@ test_description='read-tree -u --reset' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index d73a5cc237..a0481139de 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -2,7 +2,6 @@ test_description="git hash-object" -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh echo_without_newline() { diff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh index ad5936e54d..4512fb0b6e 100755 --- a/t/t1008-read-tree-overlay.sh +++ b/t/t1008-read-tree-overlay.sh @@ -5,7 +5,6 @@ test_description='test multi-tree read-tree without merging' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1009-read-tree-new-index.sh b/t/t1009-read-tree-new-index.sh index fc179ac5dd..2935f68f8d 100755 --- a/t/t1009-read-tree-new-index.sh +++ b/t/t1009-read-tree-new-index.sh @@ -5,7 +5,6 @@ test_description='test read-tree into a fresh index file' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index 22875ba598..c291a2b33d 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -2,7 +2,6 @@ test_description='git mktree' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 595b24c0ad..742f0fa909 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -12,7 +12,6 @@ test_description='sparse checkout tests ' TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh index cde93d22cd..57f0770df1 100755 --- a/t/t1012-read-tree-df.sh +++ b/t/t1012-read-tree-df.sh @@ -2,7 +2,6 @@ test_description='read-tree D/F conflict corner cases' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh index cf8b94ebed..bfc90d4cf2 100755 --- a/t/t1013-read-tree-submodule.sh +++ b/t/t1013-read-tree-submodule.sh @@ -2,7 +2,6 @@ test_description='read-tree can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t1014-read-tree-confusing.sh b/t/t1014-read-tree-confusing.sh index 8ea8d36818..0c0e6da5cf 100755 --- a/t/t1014-read-tree-confusing.sh +++ b/t/t1014-read-tree-confusing.sh @@ -2,7 +2,6 @@ test_description='check that read-tree rejects confusing paths' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create base tree' ' diff --git a/t/t1015-read-index-unmerged.sh b/t/t1015-read-index-unmerged.sh index da737a32a2..9b965d0294 100755 --- a/t/t1015-read-index-unmerged.sh +++ b/t/t1015-read-index-unmerged.sh @@ -2,7 +2,6 @@ test_description='Test various callers of read_index_unmerged' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup modify/delete + directory/file conflict' ' diff --git a/t/t1016-compatObjectFormat.sh b/t/t1016-compatObjectFormat.sh index be3206a16f..e88362fbe4 100755 --- a/t/t1016-compatObjectFormat.sh +++ b/t/t1016-compatObjectFormat.sh @@ -5,7 +5,6 @@ test_description='Test how well compatObjectFormat works' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh @@ -24,84 +23,83 @@ TEST_PASSES_SANITIZE_LEAK=true # the commit is identical to the commit in the other repository. compat_hash () { - case "$1" in - "sha1") - echo "sha256" - ;; - "sha256") - echo "sha1" - ;; - esac + case "$1" in + "sha1") + echo "sha256" + ;; + "sha256") + echo "sha1" + ;; + esac } hello_oid () { - case "$1" in - "sha1") - echo "$hello_sha1_oid" - ;; - "sha256") - echo "$hello_sha256_oid" - ;; - esac + case "$1" in + "sha1") + echo "$hello_sha1_oid" + ;; + "sha256") + echo "$hello_sha256_oid" + ;; + esac } tree_oid () { - case "$1" in - "sha1") - echo "$tree_sha1_oid" - ;; - "sha256") - echo "$tree_sha256_oid" - ;; - esac + case "$1" in + "sha1") + echo "$tree_sha1_oid" + ;; + "sha256") + echo "$tree_sha256_oid" + ;; + esac } commit_oid () { - case "$1" in - "sha1") - echo "$commit_sha1_oid" - ;; - "sha256") - echo "$commit_sha256_oid" - ;; - esac + case "$1" in + "sha1") + echo "$commit_sha1_oid" + ;; + "sha256") + echo "$commit_sha256_oid" + ;; + esac } commit2_oid () { - case "$1" in - "sha1") - echo "$commit2_sha1_oid" - ;; - "sha256") - echo "$commit2_sha256_oid" - ;; - esac + case "$1" in + "sha1") + echo "$commit2_sha1_oid" + ;; + "sha256") + echo "$commit2_sha256_oid" + ;; + esac } del_sigcommit () { - local delete="$1" - - if test "$delete" = "sha256" ; then - local pattern="gpgsig-sha256" - else - local pattern="gpgsig" - fi - test-tool delete-gpgsig "$pattern" + local delete="$1" + + if test "$delete" = "sha256" ; then + local pattern="gpgsig-sha256" + else + local pattern="gpgsig" + fi + test-tool delete-gpgsig "$pattern" } - del_sigtag () { - local storage="$1" - local delete="$2" - - if test "$storage" = "$delete" ; then - local pattern="trailer" - elif test "$storage" = "sha256" ; then - local pattern="gpgsig" - else - local pattern="gpgsig-sha256" - fi - test-tool delete-gpgsig "$pattern" + local storage="$1" + local delete="$2" + + if test "$storage" = "$delete" ; then + local pattern="trailer" + elif test "$storage" = "sha256" ; then + local pattern="gpgsig" + else + local pattern="gpgsig-sha256" + fi + test-tool delete-gpgsig "$pattern" } base=$(pwd) @@ -116,8 +114,8 @@ do git config core.repositoryformatversion 1 && git config extensions.objectformat $hash && git config extensions.compatobjectformat $(compat_hash $hash) && - git config gpg.program $TEST_DIRECTORY/t1016/gpg && - echo "Hellow World!" > hello && + test_config gpg.program $TEST_DIRECTORY/t1016/gpg && + echo "Hello World!" >hello && eval hello_${hash}_oid=$(git hash-object hello) && git update-index --add hello && git commit -m "Initial commit" && @@ -146,9 +144,9 @@ do ' test_expect_success "create a $hash branch" ' git checkout -b branch $(commit_oid $hash) && - echo "More more more give me more!" > more && + echo "More more more give me more!" >more && eval more_${hash}_oid=$(git hash-object more) && - echo "Another and another and another" > another && + echo "Another and another and another" >another && eval another_${hash}_oid=$(git hash-object another) && git update-index --add more another && git commit -m "Add more files!" && @@ -165,15 +163,15 @@ do ' test_expect_success GPG2 "create additional $hash signed commits" ' git commit --gpg-sign --allow-empty -m "This is an additional signed commit" && - git cat-file commit HEAD | del_sigcommit sha256 > "../${hash}_signedcommit3" && - git cat-file commit HEAD | del_sigcommit sha1 > "../${hash}_signedcommit4" && + git cat-file commit HEAD | del_sigcommit sha256 >"../${hash}_signedcommit3" && + git cat-file commit HEAD | del_sigcommit sha1 >"../${hash}_signedcommit4" && eval signedcommit3_${hash}_oid=$(git hash-object -t commit -w ../${hash}_signedcommit3) && eval signedcommit4_${hash}_oid=$(git hash-object -t commit -w ../${hash}_signedcommit4) ' test_expect_success GPG2 "create additional $hash signed tags" ' git tag -s -m "This is an additional signed tag" signedtag34 HEAD && - git cat-file tag signedtag34 | del_sigtag "${hash}" sha256 > ../${hash}_signedtag3 && - git cat-file tag signedtag34 | del_sigtag "${hash}" sha1 > ../${hash}_signedtag4 && + git cat-file tag signedtag34 | del_sigtag "${hash}" sha256 >../${hash}_signedtag3 && + git cat-file tag signedtag34 | del_sigtag "${hash}" sha1 >../${hash}_signedtag4 && eval signedtag3_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag3) && eval signedtag4_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag4) ' @@ -181,81 +179,80 @@ done cd "$base" compare_oids () { - test "$#" = 5 && { local PREREQ="$1"; shift; } || PREREQ= - local type="$1" - local name="$2" - local sha1_oid="$3" - local sha256_oid="$4" - - echo ${sha1_oid} > ${name}_sha1_expected - echo ${sha256_oid} > ${name}_sha256_expected - echo ${type} > ${name}_type_expected - - git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} > ${name}_sha1_sha256_found - git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha256_sha1_found - local sha1_sha256_oid="$(cat ${name}_sha1_sha256_found)" - local sha256_sha1_oid="$(cat ${name}_sha256_sha1_found)" - - test_expect_success $PREREQ "Verify ${type} ${name}'s sha1 oid" ' - git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha1 && - test_cmp ${name}_sha1 ${name}_sha1_expected -' - - test_expect_success $PREREQ "Verify ${type} ${name}'s sha256 oid" ' - git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} > ${name}_sha256 && - test_cmp ${name}_sha256 ${name}_sha256_expected -' + test "$#" = 5 && { local PREREQ="$1"; shift; } || PREREQ= + local type="$1" + local name="$2" + local sha1_oid="$3" + local sha256_oid="$4" + + echo ${sha1_oid} >${name}_sha1_expected + echo ${sha256_oid} >${name}_sha256_expected + echo ${type} >${name}_type_expected + + git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} >${name}_sha1_sha256_found + git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} >${name}_sha256_sha1_found + local sha1_sha256_oid="$(cat ${name}_sha1_sha256_found)" + local sha256_sha1_oid="$(cat ${name}_sha256_sha1_found)" + + test_expect_success $PREREQ "Verify ${type} ${name}'s sha1 oid" ' + git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} >${name}_sha1 && + test_cmp ${name}_sha1 ${name}_sha1_expected + ' - test_expect_success $PREREQ "Verify ${name}'s sha1 type" ' - git --git-dir=repo-sha1/.git cat-file -t ${sha1_oid} > ${name}_type1 && - git --git-dir=repo-sha256/.git cat-file -t ${sha256_sha1_oid} > ${name}_type2 && - test_cmp ${name}_type1 ${name}_type2 && - test_cmp ${name}_type1 ${name}_type_expected -' + test_expect_success $PREREQ "Verify ${type} ${name}'s sha256 oid" ' + git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} >${name}_sha256 && + test_cmp ${name}_sha256 ${name}_sha256_expected + ' - test_expect_success $PREREQ "Verify ${name}'s sha256 type" ' - git --git-dir=repo-sha256/.git cat-file -t ${sha256_oid} > ${name}_type3 && - git --git-dir=repo-sha1/.git cat-file -t ${sha1_sha256_oid} > ${name}_type4 && - test_cmp ${name}_type3 ${name}_type4 && - test_cmp ${name}_type3 ${name}_type_expected -' + test_expect_success $PREREQ "Verify ${name}'s sha1 type" ' + git --git-dir=repo-sha1/.git cat-file -t ${sha1_oid} >${name}_type1 && + git --git-dir=repo-sha256/.git cat-file -t ${sha256_sha1_oid} >${name}_type2 && + test_cmp ${name}_type1 ${name}_type2 && + test_cmp ${name}_type1 ${name}_type_expected + ' - test_expect_success $PREREQ "Verify ${name}'s sha1 size" ' - git --git-dir=repo-sha1/.git cat-file -s ${sha1_oid} > ${name}_size1 && - git --git-dir=repo-sha256/.git cat-file -s ${sha256_sha1_oid} > ${name}_size2 && - test_cmp ${name}_size1 ${name}_size2 -' + test_expect_success $PREREQ "Verify ${name}'s sha256 type" ' + git --git-dir=repo-sha256/.git cat-file -t ${sha256_oid} >${name}_type3 && + git --git-dir=repo-sha1/.git cat-file -t ${sha1_sha256_oid} >${name}_type4 && + test_cmp ${name}_type3 ${name}_type4 && + test_cmp ${name}_type3 ${name}_type_expected + ' - test_expect_success $PREREQ "Verify ${name}'s sha256 size" ' - git --git-dir=repo-sha256/.git cat-file -s ${sha256_oid} > ${name}_size3 && - git --git-dir=repo-sha1/.git cat-file -s ${sha1_sha256_oid} > ${name}_size4 && - test_cmp ${name}_size3 ${name}_size4 -' + test_expect_success $PREREQ "Verify ${name}'s sha1 size" ' + git --git-dir=repo-sha1/.git cat-file -s ${sha1_oid} >${name}_size1 && + git --git-dir=repo-sha256/.git cat-file -s ${sha256_sha1_oid} >${name}_size2 && + test_cmp ${name}_size1 ${name}_size2 + ' - test_expect_success $PREREQ "Verify ${name}'s sha1 pretty content" ' - git --git-dir=repo-sha1/.git cat-file -p ${sha1_oid} > ${name}_content1 && - git --git-dir=repo-sha256/.git cat-file -p ${sha256_sha1_oid} > ${name}_content2 && - test_cmp ${name}_content1 ${name}_content2 -' + test_expect_success $PREREQ "Verify ${name}'s sha256 size" ' + git --git-dir=repo-sha256/.git cat-file -s ${sha256_oid} >${name}_size3 && + git --git-dir=repo-sha1/.git cat-file -s ${sha1_sha256_oid} >${name}_size4 && + test_cmp ${name}_size3 ${name}_size4 + ' - test_expect_success $PREREQ "Verify ${name}'s sha256 pretty content" ' - git --git-dir=repo-sha256/.git cat-file -p ${sha256_oid} > ${name}_content3 && - git --git-dir=repo-sha1/.git cat-file -p ${sha1_sha256_oid} > ${name}_content4 && - test_cmp ${name}_content3 ${name}_content4 -' + test_expect_success $PREREQ "Verify ${name}'s sha1 pretty content" ' + git --git-dir=repo-sha1/.git cat-file -p ${sha1_oid} >${name}_content1 && + git --git-dir=repo-sha256/.git cat-file -p ${sha256_sha1_oid} >${name}_content2 && + test_cmp ${name}_content1 ${name}_content2 + ' - test_expect_success $PREREQ "Verify ${name}'s sha1 content" ' - git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_oid} > ${name}_content5 && - git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_sha1_oid} > ${name}_content6 && - test_cmp ${name}_content5 ${name}_content6 -' + test_expect_success $PREREQ "Verify ${name}'s sha256 pretty content" ' + git --git-dir=repo-sha256/.git cat-file -p ${sha256_oid} >${name}_content3 && + git --git-dir=repo-sha1/.git cat-file -p ${sha1_sha256_oid} >${name}_content4 && + test_cmp ${name}_content3 ${name}_content4 + ' - test_expect_success $PREREQ "Verify ${name}'s sha256 content" ' - git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_oid} > ${name}_content7 && - git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_sha256_oid} > ${name}_content8 && - test_cmp ${name}_content7 ${name}_content8 -' + test_expect_success $PREREQ "Verify ${name}'s sha1 content" ' + git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_oid} >${name}_content5 && + git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_sha1_oid} >${name}_content6 && + test_cmp ${name}_content5 ${name}_content6 + ' + test_expect_success $PREREQ "Verify ${name}'s sha256 content" ' + git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_oid} >${name}_content7 && + git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_sha256_oid} >${name}_content8 && + test_cmp ${name}_content7 ${name}_content8 + ' } compare_oids 'blob' hello "$hello_sha1_oid" "$hello_sha256_oid" diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 45eef9457f..9fdbb2af80 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -6,7 +6,6 @@ test_description='Try various core-level commands in subdirectory. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh index 69bf9476cb..0b892894eb 100755 --- a/t/t1021-rerere-in-workdir.sh +++ b/t/t1021-rerere-in-workdir.sh @@ -4,7 +4,6 @@ test_description='rerere run in a workdir' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success SYMLINKS setup ' diff --git a/t/t1022-read-tree-partial-clone.sh b/t/t1022-read-tree-partial-clone.sh index cca4380e43..d390d7d5f8 100755 --- a/t/t1022-read-tree-partial-clone.sh +++ b/t/t1022-read-tree-partial-clone.sh @@ -3,7 +3,6 @@ test_description='git read-tree in partial clones' TEST_NO_CREATE_REPO=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'read-tree in partial clone prefetches in one batch' ' diff --git a/t/t1051-large-conversion.sh b/t/t1051-large-conversion.sh index f6709c9f56..361afb679b 100755 --- a/t/t1051-large-conversion.sh +++ b/t/t1051-large-conversion.sh @@ -2,7 +2,6 @@ test_description='test conversion filters on large files' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh set_attr() { diff --git a/t/t1060-object-corruption.sh b/t/t1060-object-corruption.sh index 5e0f0a334f..502a5ea1c5 100755 --- a/t/t1060-object-corruption.sh +++ b/t/t1060-object-corruption.sh @@ -2,7 +2,6 @@ test_description='see how we handle various forms of corruption' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # convert "1234abcd" to ".git/objects/12/34abcd" diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh index da0e7714d5..3a14218b24 100755 --- a/t/t1090-sparse-checkout-scope.sh +++ b/t/t1090-sparse-checkout-scope.sh @@ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index 8c5cd651b4..ab3a105fff 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -8,7 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_SPLIT_INDEX=false export GIT_TEST_SPLIT_INDEX -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh list_files() { diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index a2c0e1b4dc..a4c7c41fc0 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -179,22 +179,26 @@ init_repos_as_submodules () { } run_on_sparse () { + cat >run-on-sparse-input && + ( cd sparse-checkout && GIT_PROGRESS_DELAY=100000 "$@" >../sparse-checkout-out 2>../sparse-checkout-err - ) && + ) <run-on-sparse-input && ( cd sparse-index && GIT_PROGRESS_DELAY=100000 "$@" >../sparse-index-out 2>../sparse-index-err - ) + ) <run-on-sparse-input } run_on_all () { + cat >run-on-all-input && + ( cd full-checkout && GIT_PROGRESS_DELAY=100000 "$@" >../full-checkout-out 2>../full-checkout-err - ) && - run_on_sparse "$@" + ) <run-on-all-input && + run_on_sparse "$@" <run-on-all-input } test_all_match () { @@ -221,7 +225,7 @@ test_sparse_unstaged () { done } -# Usage: test_sprase_checkout_set "<c1> ... <cN>" "<s1> ... <sM>" +# Usage: test_sparse_checkout_set "<c1> ... <cN>" "<s1> ... <sM>" # Verifies that "git sparse-checkout set <c1> ... <cN>" succeeds and # leaves the sparse index in a state where <s1> ... <sM> are sparse # directories (and <c1> ... <cN> are not). @@ -703,7 +707,7 @@ test_expect_success 'reset with wildcard pathspec' ' test_all_match git ls-files -s -- deep && # The following `git reset`s result in updating the index on files with - # `skip-worktree` enabled. To avoid failing due to discrepencies in reported + # `skip-worktree` enabled. To avoid failing due to discrepancies in reported # "modified" files, `test_sparse_match` reset is performed separately from # "full-checkout" reset, then the index contents of all repos are verified. @@ -803,6 +807,8 @@ test_expect_success 'update-index --remove outside sparse definition' ' test_sparse_match git diff --cached --name-status && test_cmp expect sparse-checkout-out && + test_sparse_match git diff-index --cached HEAD && + # Reset the state test_all_match git reset --hard && @@ -812,10 +818,12 @@ test_expect_success 'update-index --remove outside sparse definition' ' test_sparse_match git diff --cached --name-status && test_must_be_empty sparse-checkout-out && + test_sparse_match git diff-index --cached HEAD && + # Reset the state test_all_match git reset --hard && - # --force-remove supercedes --ignore-skip-worktree-entries, removing + # --force-remove supersedes --ignore-skip-worktree-entries, removing # a skip-worktree file from the index (and disk) when both are specified # with --remove test_sparse_match git update-index --force-remove --ignore-skip-worktree-entries folder1/a && @@ -823,7 +831,9 @@ test_expect_success 'update-index --remove outside sparse definition' ' D folder1/a EOF test_sparse_match git diff --cached --name-status && - test_cmp expect sparse-checkout-out + test_cmp expect sparse-checkout-out && + + test_sparse_match git diff-index --cached HEAD ' test_expect_success 'update-index with directories' ' @@ -1551,7 +1561,7 @@ test_expect_success 'sparse-index is not expanded: describe' ' ensure_not_expanded describe ' -test_expect_success 'sparse index is not expanded: diff' ' +test_expect_success 'sparse index is not expanded: diff and diff-index' ' init_repos && write_script edit-contents <<-\EOF && @@ -1568,6 +1578,7 @@ test_expect_success 'sparse index is not expanded: diff' ' test_all_match git diff --cached && ensure_not_expanded diff && ensure_not_expanded diff --cached && + ensure_not_expanded diff-index --cached HEAD && # Add file outside cone test_all_match git reset --hard && @@ -1582,6 +1593,7 @@ test_expect_success 'sparse index is not expanded: diff' ' test_all_match git diff --cached && ensure_not_expanded diff && ensure_not_expanded diff --cached && + ensure_not_expanded diff-index --cached HEAD && # Merge conflict outside cone # The sparse checkout will report a warning that is not in the @@ -1594,7 +1606,8 @@ test_expect_success 'sparse index is not expanded: diff' ' test_all_match git diff && test_all_match git diff --cached && ensure_not_expanded diff && - ensure_not_expanded diff --cached + ensure_not_expanded diff --cached && + ensure_not_expanded diff-index --cached HEAD ' test_expect_success 'sparse index is not expanded: show and rev-parse' ' @@ -2067,7 +2080,7 @@ test_expect_success 'grep is not expanded' ' test_expect_failure 'grep within submodules is not expanded' ' init_repos_as_submodules && - # do not use ensure_not_expanded() here, becasue `grep` should be + # do not use ensure_not_expanded() here, because `grep` should be # run in the superproject, not in "./sparse-index" GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ git grep --cached --recurse-submodules a -- "*/folder1/*" && @@ -2342,7 +2355,46 @@ test_expect_success 'advice.sparseIndexExpanded' ' mkdir -p sparse-index/deep/deeper2/deepest && touch sparse-index/deep/deeper2/deepest/bogus && git -C sparse-index status 2>err && - grep "The sparse index is expanding to a full index" err + grep "The sparse index is expanding to a full index" err && + + git -C sparse-index sparse-checkout disable 2>err && + test_line_count = 0 err +' + +test_expect_success 'cat-file -p' ' + init_repos && + echo "new content" >>full-checkout/deep/a && + echo "new content" >>sparse-checkout/deep/a && + echo "new content" >>sparse-index/deep/a && + run_on_all git add deep/a && + + test_all_match git cat-file -p :deep/a && + ensure_not_expanded cat-file -p :deep/a && + test_all_match git cat-file -p :folder1/a && + ensure_expanded cat-file -p :folder1/a +' + +test_expect_success 'cat-file --batch' ' + init_repos && + echo "new content" >>full-checkout/deep/a && + echo "new content" >>sparse-checkout/deep/a && + echo "new content" >>sparse-index/deep/a && + run_on_all git add deep/a && + + echo ":deep/a" >in && + test_all_match git cat-file --batch <in && + ensure_not_expanded cat-file --batch <in && + + echo ":folder1/a" >in && + test_all_match git cat-file --batch <in && + ensure_expanded cat-file --batch <in && + + cat >in <<-\EOF && + :deep/a + :folder1/a + EOF + test_all_match git cat-file --batch <in && + ensure_expanded cat-file --batch <in ' test_done diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index 0f37a43fd3..ae66ba5bab 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -12,7 +12,6 @@ Also make sure that command line parser understands the normal "flags first and then non flag arguments" command line. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expected <<EOF diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 9de2d95f06..51a85e83c2 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -8,7 +8,6 @@ test_description='Test git config in different settings' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh for mode in legacy subcommands @@ -2704,6 +2703,15 @@ test_expect_success '--get and --get-all with --fixed-value' ' test_must_fail git config --file=config --get-regexp --fixed-value fixed+ non-existent ' +test_expect_success '--fixed-value with value-less configuration' ' + test_when_finished rm -f config && + cat >config <<-\EOF && + [section] + key + EOF + git config --file=config --fixed-value section.key value pattern +' + test_expect_success 'includeIf.hasconfig:remote.*.url' ' git init hasremoteurlTest && test_when_finished "rm -rf hasremoteurlTest" && diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index 29cf8a9661..630a47af21 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -9,7 +9,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Remove a default ACL from the test dir if possible. diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 42caa0d297..69723b88ff 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -5,7 +5,6 @@ test_description='Test repository version check' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh index 0506f3d6bb..d971925ed0 100755 --- a/t/t1303-wacky-config.sh +++ b/t/t1303-wacky-config.sh @@ -2,7 +2,6 @@ test_description='Test wacky input to git config' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Leaving off the newline is intentional! diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh index 31b89dd969..c69ae41306 100755 --- a/t/t1304-default-acl.sh +++ b/t/t1304-default-acl.sh @@ -9,7 +9,6 @@ test_description='Test repository with default ACL' # => this must come before . ./test-lib.sh umask 077 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We need an arbitrary other user give permission to using ACLs. root diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index 5cde79ef8c..8ff2b0c232 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -1,7 +1,6 @@ #!/bin/sh test_description='test config file include directives' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Force setup_explicit_git_dir() to run until the end. This is needed @@ -357,4 +356,44 @@ test_expect_success 'include cycles are detected' ' grep "exceeded maximum include depth" stderr ' +test_expect_success 'onbranch with unborn branch' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git config set includeIf.onbranch:"*".path config.inc && + git config set -f .git/config.inc foo.bar baz && + git config get foo.bar + ) +' + +test_expect_success 'onbranch with detached HEAD' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git config set "includeIf.onbranch:*.path" config.inc && + git config set -f .git/config.inc foo.bar baz && + test_commit initial && + git switch --detach HEAD && + test_must_fail git config get foo.bar + ) +' + +test_expect_success 'onbranch without repository' ' + test_when_finished "rm -f .gitconfig config.inc" && + git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc && + git config set -f config.inc foo.bar baz && + git config get foo.bar && + test_must_fail nongit git config get foo.bar +' + +test_expect_success 'onbranch without repository but explicit nonexistent Git directory' ' + test_when_finished "rm -f .gitconfig config.inc" && + git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc && + git config set -f config.inc foo.bar baz && + git config get foo.bar && + test_must_fail nongit git --git-dir=nonexistent config get foo.bar +' + test_done diff --git a/t/t1306-xdg-files.sh b/t/t1306-xdg-files.sh index 53e5b290b9..40d3c42618 100755 --- a/t/t1306-xdg-files.sh +++ b/t/t1306-xdg-files.sh @@ -7,7 +7,6 @@ test_description='Compatibility with $XDG_CONFIG_HOME/git/ files' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'read config: xdg file exists and ~/.gitconfig doesn'\''t' ' diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh index b9852fe40e..5cb546dd00 100755 --- a/t/t1307-config-blob.sh +++ b/t/t1307-config-blob.sh @@ -2,7 +2,6 @@ test_description='support for reading config from a blob' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create config blob' ' diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index 3bfec07f1a..e0e49053f0 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -2,7 +2,6 @@ test_description='Test git config-set API in different settings' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # 'check_config get_* section.key value' verifies that the entry for diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh index 523aa99a1e..9710ee0ca4 100755 --- a/t/t1309-early-config.sh +++ b/t/t1309-early-config.sh @@ -2,7 +2,6 @@ test_description='Test read_early_config()' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'read early config' ' diff --git a/t/t1310-config-default.sh b/t/t1310-config-default.sh index 1a90d31201..69e64c6c86 100755 --- a/t/t1310-config-default.sh +++ b/t/t1310-config-default.sh @@ -2,7 +2,6 @@ test_description='Test git config in different settings (with --default)' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'uses --default when entry missing' ' diff --git a/t/t1350-config-hooks-path.sh b/t/t1350-config-hooks-path.sh index ceeb7ac3a4..45a0492917 100755 --- a/t/t1350-config-hooks-path.sh +++ b/t/t1350-config-hooks-path.sh @@ -2,7 +2,6 @@ test_description='Test the core.hooksPath configuration variable' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up a pre-commit hook in core.hooksPath' ' diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index eb1691860d..e2316f1dd4 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -5,7 +5,6 @@ test_description='Test git update-ref and basic ref logging' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh Z=$ZERO_OID @@ -1838,10 +1837,10 @@ do test_expect_success "stdin $type create dangling symref ref works" ' test_when_finished "git symbolic-ref -d refs/heads/symref" && - format_command $type "symref-create refs/heads/symref" "refs/heads/unkown" >stdin && + format_command $type "symref-create refs/heads/symref" "refs/heads/unknown" >stdin && git update-ref --stdin $type --no-deref <stdin && git symbolic-ref refs/heads/symref >expect && - echo refs/heads/unkown >actual && + echo refs/heads/unknown >actual && test_cmp expect actual ' diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index 5c60d6f812..a2a7e94716 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -2,7 +2,6 @@ test_description='basic symbolic-ref tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # If the tests munging HEAD fail, they can break detection of @@ -16,7 +15,7 @@ reset_to_sane() { test_expect_success 'setup' ' git symbolic-ref HEAD refs/heads/foo && test_commit file && - "$TAR" cf .git.tar .git/ + "$TAR" cf .git.tar .git ' test_expect_success 'symbolic-ref read/write roundtrip' ' diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index 5ed9d7318e..cabc516ae9 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -2,7 +2,6 @@ test_description='Test git check-ref-format' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh valid_ref() { diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh index 403f6b8f7d..9d698b3cc3 100755 --- a/t/t1403-show-ref.sh +++ b/t/t1403-show-ref.sh @@ -4,7 +4,6 @@ test_description='show-ref' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh index df90112618..28e6c380d7 100755 --- a/t/t1404-update-ref-errors.sh +++ b/t/t1404-update-ref-errors.sh @@ -2,7 +2,6 @@ test_description='Test git update-ref error handling' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Create some references, perhaps run pack-refs --all, then try to diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh index a6bcd62ab6..6d8f401a2a 100755 --- a/t/t1405-main-ref-store.sh +++ b/t/t1405-main-ref-store.sh @@ -5,7 +5,6 @@ test_description='test main ref store api' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh RUN="test-tool ref-store main" diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh index c01f0f14a1..9b9e5d0766 100755 --- a/t/t1406-submodule-ref-store.sh +++ b/t/t1406-submodule-ref-store.sh @@ -5,7 +5,6 @@ test_description='test submodule ref store api' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh RUN="test-tool ref-store submodule:sub" diff --git a/t/t1407-worktree-ref-store.sh b/t/t1407-worktree-ref-store.sh index 48b1c92a41..9d8e1a1343 100755 --- a/t/t1407-worktree-ref-store.sh +++ b/t/t1407-worktree-ref-store.sh @@ -5,7 +5,6 @@ test_description='test worktree ref store api' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh RWT="test-tool ref-store worktree:wt" diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh index 9469c79a58..41ba1f1d7f 100755 --- a/t/t1408-packed-refs.sh +++ b/t/t1408-packed-refs.sh @@ -5,7 +5,6 @@ test_description='packed-refs entries are covered by loose refs' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1409-avoid-packing-refs.sh b/t/t1409-avoid-packing-refs.sh index 7748973733..e3c501848a 100755 --- a/t/t1409-avoid-packing-refs.sh +++ b/t/t1409-avoid-packing-refs.sh @@ -2,7 +2,6 @@ test_description='avoid rewriting packed-refs unnecessarily' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if test_have_prereq !REFFILES diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 5bf883f1e3..388fdf9ae5 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -7,7 +7,6 @@ test_description='Test prune and reflog expiration' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_have () { @@ -146,6 +145,14 @@ test_expect_success rewind ' test_line_count = 5 output ' +test_expect_success 'reflog expire should not barf on an annotated tag' ' + test_when_finished "git tag -d v0.tag || :" && + git -c core.logAllRefUpdates=always \ + tag -a -m "tag name" v0.tag main && + git reflog expire --dry-run refs/tags/v0.tag 2>err && + test_grep ! "error: [Oo]bject .* not a commit" err +' + test_expect_success 'corrupt and check' ' corrupt $F && diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh index da581ec19a..975c4ea83a 100755 --- a/t/t1411-reflog-show.sh +++ b/t/t1411-reflog-show.sh @@ -4,7 +4,6 @@ test_description='Test reflog display routines' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index ff30874f94..f7d69b66ff 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -2,7 +2,6 @@ test_description='reflog walk shows repeated commits again' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup commits' ' diff --git a/t/t1413-reflog-detach.sh b/t/t1413-reflog-detach.sh index d2a4822d46..934688a1ee 100755 --- a/t/t1413-reflog-detach.sh +++ b/t/t1413-reflog-detach.sh @@ -4,7 +4,6 @@ test_description='Test reflog interaction with detached HEAD' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh reset_state () { diff --git a/t/t1415-worktree-refs.sh b/t/t1415-worktree-refs.sh index eb4eec8bec..51d79bae83 100755 --- a/t/t1415-worktree-refs.sh +++ b/t/t1415-worktree-refs.sh @@ -2,7 +2,6 @@ test_description='per-worktree refs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh index 5a812ca3c0..8c777f7cf8 100755 --- a/t/t1416-ref-transaction-hooks.sh +++ b/t/t1416-ref-transaction-hooks.sh @@ -5,7 +5,6 @@ test_description='reference transaction hooks' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -53,7 +52,6 @@ test_expect_success 'hook gets all queued updates in prepared state' ' fi EOF cat >expect <<-EOF && - $ZERO_OID $POST_OID HEAD $ZERO_OID $POST_OID refs/heads/main EOF git update-ref HEAD POST <<-EOF && @@ -76,7 +74,6 @@ test_expect_success 'hook gets all queued updates in committed state' ' fi EOF cat >expect <<-EOF && - $ZERO_OID $POST_OID HEAD $ZERO_OID $POST_OID refs/heads/main EOF git update-ref HEAD POST && diff --git a/t/t1417-reflog-updateref.sh b/t/t1417-reflog-updateref.sh index 0eb5e674bc..2f37402536 100755 --- a/t/t1417-reflog-updateref.sh +++ b/t/t1417-reflog-updateref.sh @@ -2,7 +2,6 @@ test_description='git reflog --updateref' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1418-reflog-exists.sh b/t/t1418-reflog-exists.sh index 2268bca3c1..d51ecd5e92 100755 --- a/t/t1418-reflog-exists.sh +++ b/t/t1418-reflog-exists.sh @@ -4,7 +4,6 @@ test_description='Test reflog display routines' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh index 1359574419..c04eeb7211 100755 --- a/t/t1419-exclude-refs.sh +++ b/t/t1419-exclude-refs.sh @@ -5,15 +5,8 @@ test_description='test exclude_patterns functionality in main ref store' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -if test_have_prereq !REFFILES -then - skip_all='skipping `git for-each-ref --exclude` tests; need files backend' - test_done -fi - for_each_ref__exclude () { GIT_TRACE2_PERF=1 test-tool ref-store main \ for-each-ref--exclude "$@" >actual.raw @@ -28,7 +21,14 @@ assert_jumps () { local nr="$1" local trace="$2" - grep -q "name:jumps_made value:$nr$" $trace + case "$GIT_DEFAULT_REF_FORMAT" in + files) + grep -q "name:jumps_made value:$nr$" $trace;; + reftable) + grep -q "name:reseeks_made value:$nr$" $trace;; + *) + BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";; + esac } assert_no_jumps () { @@ -89,7 +89,14 @@ test_expect_success 'adjacent, non-overlapping excluded regions' ' for_each_ref refs/heads/foo refs/heads/quux >expect && test_cmp expect actual && - assert_jumps 1 perf + case "$GIT_DEFAULT_REF_FORMAT" in + files) + assert_jumps 1 perf;; + reftable) + assert_jumps 2 perf;; + *) + BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";; + esac ' test_expect_success 'overlapping excluded regions' ' @@ -106,7 +113,30 @@ test_expect_success 'several overlapping excluded regions' ' for_each_ref refs/heads/quux >expect && test_cmp expect actual && - assert_jumps 1 perf + case "$GIT_DEFAULT_REF_FORMAT" in + files) + assert_jumps 1 perf;; + reftable) + assert_jumps 3 perf;; + *) + BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";; + esac +' + +test_expect_success 'unordered excludes' ' + for_each_ref__exclude refs/heads \ + refs/heads/foo refs/heads/baz >actual 2>perf && + for_each_ref refs/heads/bar refs/heads/quux >expect && + + test_cmp expect actual && + case "$GIT_DEFAULT_REF_FORMAT" in + files) + assert_jumps 1 perf;; + reftable) + assert_jumps 2 perf;; + *) + BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";; + esac ' test_expect_success 'non-matching excluded section' ' diff --git a/t/t1420-lost-found.sh b/t/t1420-lost-found.sh index dbe15a0be1..2fb2f44f02 100755 --- a/t/t1420-lost-found.sh +++ b/t/t1420-lost-found.sh @@ -5,7 +5,6 @@ test_description='Test fsck --lost-found' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 0c00118c2b..3ab65f72cd 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -4,7 +4,6 @@ test_description='Test handling of ref names that check-ref-format rejects' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t1451-fsck-buffer.sh b/t/t1451-fsck-buffer.sh index 3413da40e4..3a3d33f405 100755 --- a/t/t1451-fsck-buffer.sh +++ b/t/t1451-fsck-buffer.sh @@ -15,7 +15,6 @@ These tests _might_ catch such overruns in normal use, but should be run with ASan or valgrind for more confidence. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # the general idea for tags and commits is to build up the "base" file diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh index f7c0783d30..1bfff3a7af 100755 --- a/t/t1460-refs-migrate.sh +++ b/t/t1460-refs-migrate.sh @@ -5,7 +5,6 @@ test_description='migration of ref storage backends' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_migration () { @@ -237,7 +236,7 @@ test_expect_success 'migrating from reftable format deletes backend files' ' test_path_is_missing repo/.git/reftable && echo "ref: refs/heads/main" >expect && test_cmp expect repo/.git/HEAD && - test_path_is_file repo/.git/refs/heads/main + test_path_is_file repo/.git/packed-refs ' test_done diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh index 42c4a63cb9..58a4583088 100755 --- a/t/t1500-rev-parse.sh +++ b/t/t1500-rev-parse.sh @@ -4,7 +4,6 @@ test_description='test git rev-parse' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_one () { diff --git a/t/t1501-work-tree.sh b/t/t1501-work-tree.sh index ae6528aece..8c94ac2e70 100755 --- a/t/t1501-work-tree.sh +++ b/t/t1501-work-tree.sh @@ -2,7 +2,6 @@ test_description='test separate work tree' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index 5eaa6428c4..3962f1d288 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -2,7 +2,6 @@ test_description='test git rev-parse --parseopt' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_invalid_long_option () { diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh index 79df65ec7f..75a708f9ba 100755 --- a/t/t1503-rev-parse-verify.sh +++ b/t/t1503-rev-parse-verify.sh @@ -9,7 +9,6 @@ exec </dev/null GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh add_line_into_file() diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh index c1679e31d8..e04420f436 100755 --- a/t/t1504-ceiling-dirs.sh +++ b/t/t1504-ceiling-dirs.sh @@ -2,7 +2,6 @@ test_description='test GIT_CEILING_DIRECTORIES' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_prefix() { diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh index 4a5758f08a..2803ca9489 100755 --- a/t/t1505-rev-parse-last.sh +++ b/t/t1505-rev-parse-last.sh @@ -5,7 +5,6 @@ test_description='test @{-N} syntax' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index ef40511d89..722884e65f 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -7,7 +7,6 @@ exec </dev/null GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_did_you_mean () @@ -195,7 +194,7 @@ test_expect_success 'dotdot is not an empty set' ' ' test_expect_success 'dotdot does not peel endpoints' ' - git tag -a -m "annote" annotated HEAD && + git tag -a -m "annotate" annotated HEAD && A=$(git rev-parse annotated) && H=$(git rev-parse annotated^0) && { diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index b9af6b3ac0..cb9ef7e329 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -5,7 +5,6 @@ test_description='test <branch>@{upstream} syntax' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index e841309d0e..87a4286414 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -4,7 +4,6 @@ test_description='test various @{X} syntax combinations together' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check() { diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh index 591505a39c..bbfe05b8e4 100755 --- a/t/t1510-repo-setup.sh +++ b/t/t1510-repo-setup.sh @@ -43,7 +43,6 @@ A few rules for repo setup: # This test heavily relies on the standard error of nested function calls. test_untraceable=UnfortunatelyYes -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh here=$(pwd) diff --git a/t/t1511-rev-parse-caret.sh b/t/t1511-rev-parse-caret.sh index e7e78a4028..6ecfed86bc 100755 --- a/t/t1511-rev-parse-caret.sh +++ b/t/t1511-rev-parse-caret.sh @@ -5,7 +5,6 @@ test_description='tests for ref^{stuff}' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index f9d68ce74e..70f1e0a998 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -23,7 +23,6 @@ one tagged as v1.0.0. They all have one regular file each. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_cmp_failed_rev_parse () { diff --git a/t/t1513-rev-parse-prefix.sh b/t/t1513-rev-parse-prefix.sh index ba43387bf1..5f437be8c9 100755 --- a/t/t1513-rev-parse-prefix.sh +++ b/t/t1513-rev-parse-prefix.sh @@ -5,7 +5,6 @@ test_description='Tests for rev-parse --prefix' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1514-rev-parse-push.sh b/t/t1514-rev-parse-push.sh index a835a196aa..d868a08110 100755 --- a/t/t1514-rev-parse-push.sh +++ b/t/t1514-rev-parse-push.sh @@ -4,7 +4,6 @@ test_description='test <branch>@{push} syntax' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh resolve () { diff --git a/t/t1515-rev-parse-outside-repo.sh b/t/t1515-rev-parse-outside-repo.sh index cdb26a30d7..75e89c4b6e 100755 --- a/t/t1515-rev-parse-outside-repo.sh +++ b/t/t1515-rev-parse-outside-repo.sh @@ -2,7 +2,6 @@ test_description='check that certain rev-parse options work outside repo' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up non-repo directory' ' diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh index 990a036582..dbd8cd6906 100755 --- a/t/t1517-outside-repo.sh +++ b/t/t1517-outside-repo.sh @@ -2,7 +2,6 @@ test_description='check random commands outside repo' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up a non-repo directory and test file' ' @@ -98,7 +97,7 @@ test_expect_success 'stripspace outside repository' ' nongit git stripspace -s </dev/null ' -test_expect_success 'remote-http outside repository' ' +test_expect_success LIBCURL 'remote-http outside repository' ' test_must_fail git remote-http 2>actual && test_grep "^error: remote-curl" actual && ( diff --git a/t/t1600-index.sh b/t/t1600-index.sh index 62e7fd1596..03239e9faa 100755 --- a/t/t1600-index.sh +++ b/t/t1600-index.sh @@ -2,7 +2,6 @@ test_description='index file specific tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh sane_unset GIT_TEST_SPLIT_INDEX diff --git a/t/t1601-index-bogus.sh b/t/t1601-index-bogus.sh index 4171f1e141..a45a8b4eb0 100755 --- a/t/t1601-index-bogus.sh +++ b/t/t1601-index-bogus.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test handling of bogus index entries' + . ./test-lib.sh test_expect_success 'create tree with null sha1' ' diff --git a/t/t1701-racy-split-index.sh b/t/t1701-racy-split-index.sh index d8fa489998..5dc221ef38 100755 --- a/t/t1701-racy-split-index.sh +++ b/t/t1701-racy-split-index.sh @@ -5,7 +5,6 @@ test_description='racy split index' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh index 8b0234cf2d..4feaf0d7be 100755 --- a/t/t1800-hook.sh +++ b/t/t1800-hook.sh @@ -2,7 +2,6 @@ test_description='git-hook command' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh diff --git a/t/t2000-conflict-when-checking-files-out.sh b/t/t2000-conflict-when-checking-files-out.sh index 79fc97f1d7..f18616ad2b 100755 --- a/t/t2000-conflict-when-checking-files-out.sh +++ b/t/t2000-conflict-when-checking-files-out.sh @@ -21,7 +21,6 @@ test_description='git conflicts when checking files out test.' # path1 is occupied by a non-directory. With "-f" flag, it should remove # the conflicting paths and succeed. -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh show_files() { diff --git a/t/t2002-checkout-cache-u.sh b/t/t2002-checkout-cache-u.sh index fc95cf9048..70361c806e 100755 --- a/t/t2002-checkout-cache-u.sh +++ b/t/t2002-checkout-cache-u.sh @@ -8,7 +8,6 @@ test_description='git checkout-index -u test. With -u flag, git checkout-index internally runs the equivalent of git update-index --refresh on the checked out entry.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success \ diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh index f0fd441d81..ff163cf675 100755 --- a/t/t2003-checkout-cache-mkdir.sh +++ b/t/t2003-checkout-cache-mkdir.sh @@ -10,7 +10,6 @@ also verifies that such leading path may contain symlinks, unlike the GIT controlled paths. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index 98e818f09f..b92d96fdc4 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -8,7 +8,6 @@ test_description='git checkout-index --temp test. With --temp flag, git checkout-index writes to temporary merge files rather than the tracked path.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh index 67d18cfa10..91b08e0371 100755 --- a/t/t2005-checkout-index-symlinks.sh +++ b/t/t2005-checkout-index-symlinks.sh @@ -8,7 +8,6 @@ test_description='git checkout-index on filesystem w/o symlinks test. This tests that git checkout-index creates a symbolic link as a plain file if core.symlinks is false.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success \ diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh index 570ba38580..bac231b167 100755 --- a/t/t2006-checkout-index-basic.sh +++ b/t/t2006-checkout-index-basic.sh @@ -3,7 +3,6 @@ test_description='basic checkout-index tests ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'checkout-index --gobbledegook' ' diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh index bd9e9e7530..6f0b90ce12 100755 --- a/t/t2007-checkout-symlink.sh +++ b/t/t2007-checkout-symlink.sh @@ -7,7 +7,6 @@ test_description='git checkout to switch between branches with symlink<->dir' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2008-checkout-subdir.sh b/t/t2008-checkout-subdir.sh index 8a518a44ea..eadb9434ae 100755 --- a/t/t2008-checkout-subdir.sh +++ b/t/t2008-checkout-subdir.sh @@ -4,7 +4,6 @@ test_description='git checkout from subdirectories' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2009-checkout-statinfo.sh b/t/t2009-checkout-statinfo.sh index 71195dd28f..b0540636ae 100755 --- a/t/t2009-checkout-statinfo.sh +++ b/t/t2009-checkout-statinfo.sh @@ -5,7 +5,6 @@ test_description='checkout should leave clean stat info' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh index 82c3bfeac1..3a3d56018e 100755 --- a/t/t2010-checkout-ambiguous.sh +++ b/t/t2010-checkout-ambiguous.sh @@ -5,7 +5,6 @@ test_description='checkout and pathspecs/refspecs ambiguities' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh index 04f53b1ea1..61417c7567 100755 --- a/t/t2011-checkout-invalid-head.sh +++ b/t/t2011-checkout-invalid-head.sh @@ -5,7 +5,6 @@ test_description='checkout switching away from an invalid branch' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh index 4b6372f4c3..1f6c4ed042 100755 --- a/t/t2012-checkout-last.sh +++ b/t/t2012-checkout-last.sh @@ -5,7 +5,6 @@ test_description='checkout can switch to last branch and merge base' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index 3c1d663d94..b2bdd1fcb4 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -2,7 +2,6 @@ test_description='checkout can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t2014-checkout-switch.sh b/t/t2014-checkout-switch.sh index c138bdde4f..3e757c6e4e 100755 --- a/t/t2014-checkout-switch.sh +++ b/t/t2014-checkout-switch.sh @@ -2,7 +2,6 @@ test_description='Peter MacMillan' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh index fb0e13881c..1820300c62 100755 --- a/t/t2015-checkout-unborn.sh +++ b/t/t2015-checkout-unborn.sh @@ -4,7 +4,6 @@ test_description='checkout from unborn branch' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh index c40b661ac1..c4f9bf09aa 100755 --- a/t/t2016-checkout-patch.sh +++ b/t/t2016-checkout-patch.sh @@ -2,7 +2,6 @@ test_description='git checkout --patch' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh test_expect_success 'setup' ' diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh index a5c7358eea..80ac661815 100755 --- a/t/t2017-checkout-orphan.sh +++ b/t/t2017-checkout-orphan.sh @@ -10,7 +10,6 @@ Main Tests for --orphan functionality.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh TEST_FILE=foo diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 43551cc148..a48ebdbf4d 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -3,7 +3,6 @@ test_description='checkout' TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Arguments: [!] <branch> <oid> [<checkout options>] diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh index c67261e2b6..1fcef4be95 100755 --- a/t/t2019-checkout-ambiguous-ref.sh +++ b/t/t2019-checkout-ambiguous-ref.sh @@ -2,7 +2,6 @@ test_description='checkout handling of ambiguous (branch/tag) refs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ambiguous refs' ' diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 8d90d02850..28bbbe6c05 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -4,7 +4,6 @@ test_description='checkout into detached HEAD state' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_detached () { diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh index ecfacf0f7f..a5c03d5d4a 100755 --- a/t/t2021-checkout-overwrite.sh +++ b/t/t2021-checkout-overwrite.sh @@ -2,7 +2,6 @@ test_description='checkout must not overwrite an untracked objects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh index f1b709d58b..c49ba7f9bd 100755 --- a/t/t2022-checkout-paths.sh +++ b/t/t2022-checkout-paths.sh @@ -4,7 +4,6 @@ test_description='checkout $tree -- $paths' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2023-checkout-m.sh b/t/t2023-checkout-m.sh index 81e772fb4e..7b327b7544 100755 --- a/t/t2023-checkout-m.sh +++ b/t/t2023-checkout-m.sh @@ -7,7 +7,6 @@ Ensures that checkout -m on a resolved file restores the conflicted file' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index 2caada3d83..a3b1449ef1 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -4,7 +4,6 @@ test_description='checkout <branch> Ensures that checkout on an unborn branch does what the user expects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Is the current branch "refs/heads/$1"? diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh index 246609d54d..dda169bbc4 100755 --- a/t/t2025-checkout-no-overlay.sh +++ b/t/t2025-checkout-no-overlay.sh @@ -2,7 +2,6 @@ test_description='checkout --no-overlay <tree-ish> -- <pathspec>' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2026-checkout-pathspec-file.sh b/t/t2026-checkout-pathspec-file.sh index acd55217a6..161da054b6 100755 --- a/t/t2026-checkout-pathspec-file.sh +++ b/t/t2026-checkout-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='checkout --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t2027-checkout-track.sh b/t/t2027-checkout-track.sh index 98f16c7239..a397790df5 100755 --- a/t/t2027-checkout-track.sh +++ b/t/t2027-checkout-track.sh @@ -5,7 +5,6 @@ test_description='tests for git branch --track' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index b3f6bc97b5..be3fcdde07 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -5,7 +5,6 @@ test_description='undoing resolution' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_resolve_undo () { diff --git a/t/t2050-git-dir-relative.sh b/t/t2050-git-dir-relative.sh index 1f193cde96..21f4659a9d 100755 --- a/t/t2050-git-dir-relative.sh +++ b/t/t2050-git-dir-relative.sh @@ -12,7 +12,6 @@ into the subdir while keeping the worktree location, and tries commits from the top and the subdir, checking that the commit-hook still gets called.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh COMMIT_FILE="$(pwd)/output" diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh index 77b2346291..c91c4db936 100755 --- a/t/t2060-switch.sh +++ b/t/t2060-switch.sh @@ -5,7 +5,6 @@ test_description='switch basic functionality' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index ac404945d4..16d6348b69 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -5,7 +5,6 @@ test_description='restore basic functionality' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh index 42d5522119..27e85be40a 100755 --- a/t/t2071-restore-patch.sh +++ b/t/t2071-restore-patch.sh @@ -2,7 +2,6 @@ test_description='git restore --patch' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh test_expect_success 'setup' ' diff --git a/t/t2072-restore-pathspec-file.sh b/t/t2072-restore-pathspec-file.sh index 86c9c88788..8198a1e578 100755 --- a/t/t2072-restore-pathspec-file.sh +++ b/t/t2072-restore-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='restore --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t2080-parallel-checkout-basics.sh b/t/t2080-parallel-checkout-basics.sh index 59e5570cb2..5ffe1a41e2 100755 --- a/t/t2080-parallel-checkout-basics.sh +++ b/t/t2080-parallel-checkout-basics.sh @@ -8,7 +8,6 @@ working tree. ' TEST_NO_CREATE_REPO=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-parallel-checkout.sh" diff --git a/t/t2081-parallel-checkout-collisions.sh b/t/t2081-parallel-checkout-collisions.sh index 6acdb89d12..f6fcfc0c1e 100755 --- a/t/t2081-parallel-checkout-collisions.sh +++ b/t/t2081-parallel-checkout-collisions.sh @@ -11,7 +11,6 @@ The tests in this file exercise parallel checkout's collision detection code in both these mechanics. " -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-parallel-checkout.sh" diff --git a/t/t2082-parallel-checkout-attributes.sh b/t/t2082-parallel-checkout-attributes.sh index aec55496eb..79fb11f139 100755 --- a/t/t2082-parallel-checkout-attributes.sh +++ b/t/t2082-parallel-checkout-attributes.sh @@ -10,7 +10,6 @@ properly (without access to the index or attribute stack). ' TEST_NO_CREATE_REPO=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-parallel-checkout.sh" . "$TEST_DIRECTORY/lib-encoding.sh" @@ -34,7 +33,7 @@ test_expect_success 'parallel-checkout with ident' ' ) ' -test_expect_success 'parallel-checkout with re-encoding' ' +test_expect_success ICONV 'parallel-checkout with re-encoding' ' set_checkout_config 2 0 && git init encoding && ( @@ -91,7 +90,7 @@ test_expect_success 'parallel-checkout with eol conversions' ' # Entries that require an external filter are not eligible for parallel # checkout. Check that both the parallel-eligible and non-eligible entries are -# properly writen in a single checkout operation. +# properly written in a single checkout operation. # test_expect_success 'parallel-checkout and external filter' ' set_checkout_config 2 0 && diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh index 7915e7b821..2df3fdde8b 100755 --- a/t/t2100-update-cache-badpath.sh +++ b/t/t2100-update-cache-badpath.sh @@ -22,7 +22,6 @@ and tries to git update-index --add the following: All of the attempts should fail. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh mkdir path2 path3 diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh index e3c7acdbf9..6c32d42c8c 100755 --- a/t/t2101-update-index-reupdate.sh +++ b/t/t2101-update-index-reupdate.sh @@ -6,7 +6,6 @@ test_description='git update-index --again test. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'update-index --add' ' diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh index c49cdfb6e5..9b11130ab9 100755 --- a/t/t2102-update-index-symlinks.sh +++ b/t/t2102-update-index-symlinks.sh @@ -8,7 +8,6 @@ test_description='git update-index on filesystem w/o symlinks test. This tests that git update-index keeps the symbolic link property even if a plain file is in the working tree if core.symlinks is false.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success \ diff --git a/t/t2103-update-index-ignore-missing.sh b/t/t2103-update-index-ignore-missing.sh index e9451cd567..6938ecca86 100755 --- a/t/t2103-update-index-ignore-missing.sh +++ b/t/t2103-update-index-ignore-missing.sh @@ -2,7 +2,6 @@ test_description='update-index with options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success basics ' diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh index 7ec7f30b44..7a0778ed98 100755 --- a/t/t2104-update-index-skip-worktree.sh +++ b/t/t2104-update-index-skip-worktree.sh @@ -5,7 +5,6 @@ test_description='skip-worktree bit test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh sane_unset GIT_TEST_SPLIT_INDEX diff --git a/t/t2105-update-index-gitfile.sh b/t/t2105-update-index-gitfile.sh index 963ebe77eb..a7f3d47aec 100755 --- a/t/t2105-update-index-gitfile.sh +++ b/t/t2105-update-index-gitfile.sh @@ -6,7 +6,6 @@ test_description='git update-index for gitlink to .git file. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'submodule with absolute .git file' ' diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh index 95c004dc5c..6b2ccc21a9 100755 --- a/t/t2106-update-index-assume-unchanged.sh +++ b/t/t2106-update-index-assume-unchanged.sh @@ -3,7 +3,6 @@ test_description='git update-index --assume-unchanged test. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2108-update-index-refresh-racy.sh b/t/t2108-update-index-refresh-racy.sh index bc5f2886fa..b31dd8ece5 100755 --- a/t/t2108-update-index-refresh-racy.sh +++ b/t/t2108-update-index-refresh-racy.sh @@ -2,7 +2,6 @@ test_description='update-index refresh tests related to racy timestamps' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh reset_files () { diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index df235ac306..06e83d3333 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -14,7 +14,6 @@ only the updates to dir/sub. Also tested are "git add -u" without limiting, and "git add -u" without contents changes, and other conditions' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh index dba62d69c6..687be974d4 100755 --- a/t/t2201-add-update-typechange.sh +++ b/t/t2201-add-update-typechange.sh @@ -2,7 +2,6 @@ test_description='more git add -u' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh index 24c60bfd79..9ee659098c 100755 --- a/t/t2202-add-addremove.sh +++ b/t/t2202-add-addremove.sh @@ -2,7 +2,6 @@ test_description='git add --all' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index 8fa44a92a2..192ad14b5f 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -2,7 +2,6 @@ test_description='Intent to add' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'intent to add' ' diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh index b7cf1e492c..31eb233df5 100755 --- a/t/t2204-add-ignored.sh +++ b/t/t2204-add-ignored.sh @@ -2,7 +2,6 @@ test_description='giving ignored paths to git add' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t2205-add-worktree-config.sh b/t/t2205-add-worktree-config.sh index 98265ba1b4..43d950de64 100755 --- a/t/t2205-add-worktree-config.sh +++ b/t/t2205-add-worktree-config.sh @@ -17,7 +17,6 @@ outside the repository. Two instances for which this can occur are tested: repository can be added to the index. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success '1a: setup--config worktree' ' diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh index b40eeb263f..c8de6d8a19 100755 --- a/t/t2300-cd-to-toplevel.sh +++ b/t/t2300-cd-to-toplevel.sh @@ -2,7 +2,6 @@ test_description='cd_to_toplevel' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh EXEC_PATH="$(git --exec-path)" diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index cfc4aeb179..90638fa886 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh @@ -1207,4 +1206,50 @@ test_expect_success '"add" with initialized submodule, with submodule.recurse se git -C project-clone -c submodule.recurse worktree add ../project-5 ' +test_expect_success 'can create worktrees with relative paths' ' + test_when_finished "git worktree remove relative" && + test_config worktree.useRelativePaths false && + git worktree add --relative-paths ./relative && + echo "gitdir: ../.git/worktrees/relative" >expect && + test_cmp expect relative/.git && + echo "../../../relative/.git" >expect && + test_cmp expect .git/worktrees/relative/gitdir +' + +test_expect_success 'can create worktrees with absolute paths' ' + test_config worktree.useRelativePaths true && + git worktree add ./relative && + echo "gitdir: ../.git/worktrees/relative" >expect && + test_cmp expect relative/.git && + git worktree add --no-relative-paths ./absolute && + echo "gitdir: $(pwd)/.git/worktrees/absolute" >expect && + test_cmp expect absolute/.git && + echo "$(pwd)/absolute/.git" >expect && + test_cmp expect .git/worktrees/absolute/gitdir +' + +test_expect_success 'move repo without breaking relative internal links' ' + test_when_finished rm -rf repo moved && + git init repo && + ( + cd repo && + test_commit initial && + git worktree add --relative-paths wt1 && + cd .. && + mv repo moved && + cd moved/wt1 && + git worktree list >out 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'relative worktree sets extension config' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo commit --allow-empty -m base && + git -C repo worktree add --relative-paths ./foo && + test_cmp_config -C repo 1 core.repositoryformatversion && + test_cmp_config -C repo true extensions.relativeworktrees +' + test_done diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index 71aa9bcd62..fe671d4197 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -5,7 +5,6 @@ test_description='prune $GIT_DIR/worktrees' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success initialize ' @@ -120,4 +119,24 @@ test_expect_success 'prune duplicate (main/linked)' ' ! test -d .git/worktrees/wt ' +test_expect_success 'not prune proper worktrees inside linked worktree with relative paths' ' + test_when_finished rm -rf repo wt_ext && + git init repo && + ( + cd repo && + git config worktree.useRelativePaths true && + echo content >file && + git add file && + git commit -m msg && + git worktree add ../wt_ext && + git worktree add wt_int && + cd wt_int && + git worktree prune -v >out && + test_must_be_empty out && + cd ../../wt_ext && + git worktree prune -v >out && + test_must_be_empty out + ) +' + test_done diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh index 33ea9cb21b..8ef1cad7f2 100755 --- a/t/t2402-worktree-list.sh +++ b/t/t2402-worktree-list.sh @@ -5,7 +5,6 @@ test_description='test git worktree list' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -261,6 +260,7 @@ test_expect_success 'broken main worktree still at the top' ' ' test_expect_success 'linked worktrees are sorted' ' + test_when_finished "rm -rf sorted" && mkdir sorted && git init sorted/main && ( @@ -280,6 +280,27 @@ test_expect_success 'linked worktrees are sorted' ' test_cmp expected sorted/main/actual ' +test_expect_success 'linked worktrees with relative paths are shown with absolute paths' ' + test_when_finished "rm -rf sorted" && + mkdir sorted && + git init sorted/main && + ( + cd sorted/main && + test_tick && + test_commit new && + git worktree add --relative-paths ../first && + git worktree add ../second && + git worktree list --porcelain >out && + grep ^worktree out >actual + ) && + cat >expected <<-EOF && + worktree $(pwd)/sorted/main + worktree $(pwd)/sorted/first + worktree $(pwd)/sorted/second + EOF + test_cmp expected sorted/main/actual +' + test_expect_success 'worktree path when called in .git directory' ' git worktree list >list1 && git -C .git worktree list >list2 && diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh index 901342ea09..0bb33e8b1b 100755 --- a/t/t2403-worktree-move.sh +++ b/t/t2403-worktree-move.sh @@ -2,7 +2,6 @@ test_description='test git worktree move, remove, lock and unlock' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -247,4 +246,29 @@ test_expect_success 'not remove a repo with initialized submodule' ' ) ' +test_expect_success 'move worktree with absolute path to relative path' ' + test_config worktree.useRelativePaths false && + git worktree add ./absolute && + git worktree move --relative-paths absolute relative && + echo "gitdir: ../.git/worktrees/absolute" >expect && + test_cmp expect relative/.git && + echo "../../../relative/.git" >expect && + test_cmp expect .git/worktrees/absolute/gitdir && + test_config worktree.useRelativePaths true && + git worktree move relative relative2 && + echo "gitdir: ../.git/worktrees/absolute" >expect && + test_cmp expect relative2/.git && + echo "../../../relative2/.git" >expect && + test_cmp expect .git/worktrees/absolute/gitdir +' + +test_expect_success 'move worktree with relative path to absolute path' ' + test_config worktree.useRelativePaths true && + git worktree move --no-relative-paths relative2 absolute && + echo "gitdir: $(pwd)/.git/worktrees/absolute" >expect && + test_cmp expect absolute/.git && + echo "$(pwd)/absolute/.git" >expect && + test_cmp expect .git/worktrees/absolute/gitdir +' + test_done diff --git a/t/t2404-worktree-config.sh b/t/t2404-worktree-config.sh index 842937bfb9..9536d10919 100755 --- a/t/t2404-worktree-config.sh +++ b/t/t2404-worktree-config.sh @@ -2,7 +2,6 @@ test_description="config file in multi worktree" -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t2405-worktree-submodule.sh b/t/t2405-worktree-submodule.sh index 1d7f605633..11018f37c7 100755 --- a/t/t2405-worktree-submodule.sh +++ b/t/t2405-worktree-submodule.sh @@ -5,7 +5,6 @@ test_description='Combination of submodules and multiple worktrees' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh base_path=$(pwd -P) diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh index edbf502ec5..f5f19b3169 100755 --- a/t/t2406-worktree-repair.sh +++ b/t/t2406-worktree-repair.sh @@ -2,7 +2,6 @@ test_description='test git worktree repair' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -197,4 +196,62 @@ test_expect_success 'repair moved main and linked worktrees' ' test_cmp expect-gitfile sidemoved/.git ' +test_expect_success 'repair copied main and linked worktrees' ' + test_when_finished "rm -rf orig dup" && + mkdir -p orig && + git -C orig init main && + test_commit -C orig/main nothing && + git -C orig/main worktree add ../linked && + cp orig/main/.git/worktrees/linked/gitdir orig/main.expect && + cp orig/linked/.git orig/linked.expect && + cp -R orig dup && + sed "s,orig/linked/\.git$,dup/linked/.git," orig/main.expect >dup/main.expect && + sed "s,orig/main/\.git/worktrees/linked$,dup/main/.git/worktrees/linked," \ + orig/linked.expect >dup/linked.expect && + git -C dup/main worktree repair ../linked && + test_cmp orig/main.expect orig/main/.git/worktrees/linked/gitdir && + test_cmp orig/linked.expect orig/linked/.git && + test_cmp dup/main.expect dup/main/.git/worktrees/linked/gitdir && + test_cmp dup/linked.expect dup/linked/.git +' + +test_expect_success 'repair worktree with relative path with missing gitfile' ' + test_when_finished "rm -rf main wt" && + test_create_repo main && + git -C main config worktree.useRelativePaths true && + test_commit -C main init && + git -C main worktree add --detach ../wt && + rm wt/.git && + test_path_is_missing wt/.git && + git -C main worktree repair && + echo "gitdir: ../main/.git/worktrees/wt" >expect && + test_cmp expect wt/.git +' + +test_expect_success 'repair absolute worktree to use relative paths' ' + test_when_finished "rm -rf main side sidemoved" && + test_create_repo main && + test_commit -C main init && + git -C main worktree add --detach ../side && + echo "../../../../sidemoved/.git" >expect-gitdir && + echo "gitdir: ../main/.git/worktrees/side" >expect-gitfile && + mv side sidemoved && + git -C main worktree repair --relative-paths ../sidemoved && + test_cmp expect-gitdir main/.git/worktrees/side/gitdir && + test_cmp expect-gitfile sidemoved/.git +' + +test_expect_success 'repair relative worktree to use absolute paths' ' + test_when_finished "rm -rf main side sidemoved" && + test_create_repo main && + test_commit -C main init && + git -C main worktree add --relative-paths --detach ../side && + echo "$(pwd)/sidemoved/.git" >expect-gitdir && + echo "gitdir: $(pwd)/main/.git/worktrees/side" >expect-gitfile && + mv side sidemoved && + git -C main worktree repair ../sidemoved && + test_cmp expect-gitdir main/.git/worktrees/side/gitdir && + test_cmp expect-gitfile sidemoved/.git +' + test_done diff --git a/t/t2407-worktree-heads.sh b/t/t2407-worktree-heads.sh index f6835c91dc..57c201869f 100755 --- a/t/t2407-worktree-heads.sh +++ b/t/t2407-worktree-heads.sh @@ -2,7 +2,6 @@ test_description='test operations trying to overwrite refs at worktree HEAD' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -49,7 +48,7 @@ test_expect_success 'refuse to overwrite: checked out in worktree' ' done ' -test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' ' +test_expect_success 'refuse to overwrite: worktree in bisect' ' test_when_finished git -C wt-4 bisect reset && # Set up a bisect so HEAD no longer points to wt-4. @@ -61,7 +60,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' ' grep "cannot force update the branch '\''wt-4'\'' used by worktree at.*wt-4" err ' -test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (apply)' ' +test_expect_success 'refuse to overwrite: worktree in rebase (apply)' ' test_when_finished git -C wt-2 rebase --abort && # This will fail part-way through due to a conflict. @@ -71,7 +70,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (app grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err ' -test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (merge)' ' +test_expect_success 'refuse to overwrite: worktree in rebase (merge)' ' test_when_finished git -C wt-2 rebase --abort && # This will fail part-way through due to a conflict. @@ -81,7 +80,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err ' -test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with --update-refs' ' +test_expect_success 'refuse to overwrite: worktree in rebase with --update-refs' ' test_when_finished git -C wt-3 rebase --abort && git branch -f can-be-updated wt-3 && @@ -95,7 +94,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with done ' -test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: checked out' ' +test_expect_success 'refuse to fetch over ref: checked out' ' test_must_fail git fetch server +refs/heads/wt-3:refs/heads/wt-3 2>err && grep "refusing to fetch into branch '\''refs/heads/wt-3'\''" err && @@ -105,7 +104,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: checked out' ' grep "refusing to fetch into branch" err ' -test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: worktree in bisect' ' +test_expect_success 'refuse to fetch over ref: worktree in bisect' ' test_when_finished git -C wt-4 bisect reset && # Set up a bisect so HEAD no longer points to wt-4. @@ -117,7 +116,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: worktree in bisect grep "refusing to fetch into branch" err ' -test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: worktree in rebase' ' +test_expect_success 'refuse to fetch over ref: worktree in rebase' ' test_when_finished git -C wt-3 rebase --abort && # This will fail part-way through due to a conflict. @@ -157,7 +156,7 @@ test_expect_success 'refuse to overwrite when in error states' ' . "$TEST_DIRECTORY"/lib-rebase.sh -test_expect_success !SANITIZE_LEAK 'refuse to overwrite during rebase with --update-refs' ' +test_expect_success 'refuse to overwrite during rebase with --update-refs' ' git commit --fixup HEAD~2 --allow-empty && ( set_cat_todo_editor && diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh index 714feb83be..5c0bf4d21f 100755 --- a/t/t2500-untracked-overwriting.sh +++ b/t/t2500-untracked-overwriting.sh @@ -2,7 +2,6 @@ test_description='Test handling of overwriting untracked files' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_setup_reset () { diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 8af4e8cfe3..f6d8d7d03d 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -2,7 +2,6 @@ test_description='Test handling of the current working directory becoming empty' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 11af4552f7..13f66fd649 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -16,7 +16,6 @@ filesystem. path4 - an empty directory ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ' ' diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh index 1ed0aa967e..4b67646285 100755 --- a/t/t3001-ls-files-others-exclude.sh +++ b/t/t3001-ls-files-others-exclude.sh @@ -8,7 +8,6 @@ test_description='git ls-files --others --exclude This test runs git ls-files --others and tests --exclude patterns. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh rm -fr one three diff --git a/t/t3002-ls-files-dashpath.sh b/t/t3002-ls-files-dashpath.sh index 4dd24550eb..31462cb441 100755 --- a/t/t3002-ls-files-dashpath.sh +++ b/t/t3002-ls-files-dashpath.sh @@ -13,7 +13,6 @@ filesystem. -- - another file with a funny name. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh index 7933dff9b3..ac3c811f46 100755 --- a/t/t3003-ls-files-exclude.sh +++ b/t/t3003-ls-files-exclude.sh @@ -2,7 +2,6 @@ test_description='ls-files --exclude does not affect index files' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create repo with file' ' diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh index 12e41a7b40..a1078f8701 100755 --- a/t/t3004-ls-files-basic.sh +++ b/t/t3004-ls-files-basic.sh @@ -6,7 +6,6 @@ This test runs git ls-files with various unusual or malformed command-line arguments. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'ls-files in empty repository' ' diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh index fbfa210a50..db13aabf62 100755 --- a/t/t3005-ls-files-relative.sh +++ b/t/t3005-ls-files-relative.sh @@ -5,7 +5,6 @@ test_description='ls-files tests with relative paths This test runs git ls-files with various relative path arguments. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'prepare' ' diff --git a/t/t3006-ls-files-long.sh b/t/t3006-ls-files-long.sh index 2aaf91ebc8..22c7256c3a 100755 --- a/t/t3006-ls-files-long.sh +++ b/t/t3006-ls-files-long.sh @@ -2,7 +2,6 @@ test_description='overly long paths' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh index f04bdc8c78..61771eec83 100755 --- a/t/t3007-ls-files-recurse-submodules.sh +++ b/t/t3007-ls-files-recurse-submodules.sh @@ -6,7 +6,6 @@ This test verifies the recurse-submodules feature correctly lists files from submodules. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup directory structure and submodules' ' diff --git a/t/t3008-ls-files-lazy-init-name-hash.sh b/t/t3008-ls-files-lazy-init-name-hash.sh index 51d3dffaa6..85f3704958 100755 --- a/t/t3008-ls-files-lazy-init-name-hash.sh +++ b/t/t3008-ls-files-lazy-init-name-hash.sh @@ -2,7 +2,6 @@ test_description='Test the lazy init name hash with various folder structures' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if test 1 -eq $(test-tool online-cpus) diff --git a/t/t3009-ls-files-others-nonsubmodule.sh b/t/t3009-ls-files-others-nonsubmodule.sh index 14218b3424..963f3462b7 100755 --- a/t/t3009-ls-files-others-nonsubmodule.sh +++ b/t/t3009-ls-files-others-nonsubmodule.sh @@ -18,7 +18,6 @@ This test runs git ls-files --others with the following working tree: git repository with a commit and an untracked file ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup: directories' ' diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh index 054178703d..7af4532cd1 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -42,7 +42,6 @@ We should report path0, path1, path2/file2, path3/file3, path7 and path8 modified without reporting path9 and path10. submod1 is also modified. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'git update-index --add to add various paths.' ' diff --git a/t/t3012-ls-files-dedup.sh b/t/t3012-ls-files-dedup.sh index 190e2f6eed..2682b1f43a 100755 --- a/t/t3012-ls-files-dedup.sh +++ b/t/t3012-ls-files-dedup.sh @@ -2,7 +2,6 @@ test_description='git ls-files --deduplicate test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh index 6e6ea0b6f3..8bdaacd85a 100755 --- a/t/t3013-ls-files-format.sh +++ b/t/t3013-ls-files-format.sh @@ -2,7 +2,6 @@ test_description='git ls-files --format test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh for flag in -s -o -k -t --resolve-undo --deduplicate --eol diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh index 133593d23c..ac82c9cee8 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -10,7 +10,6 @@ returns an error when a non-existent path is provided on the command line. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh index bd65dfcffc..768d702fbb 100755 --- a/t/t3040-subprojects-basic.sh +++ b/t/t3040-subprojects-basic.sh @@ -2,7 +2,6 @@ test_description='Basic subproject functionality' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup: create superproject' ' diff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh index 3884694165..f1f09abdd9 100755 --- a/t/t3050-subprojects-fetch.sh +++ b/t/t3050-subprojects-fetch.sh @@ -2,7 +2,6 @@ test_description='fetching and pushing project with subproject' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh index 5a06732ca7..eb69da61fe 100755 --- a/t/t3060-ls-files-with-tree.sh +++ b/t/t3060-ls-files-with-tree.sh @@ -9,7 +9,6 @@ This test runs git ls-files --with-tree and in particular in a scenario known to trigger a crash with some versions of git. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 4dd42df38c..3da824117c 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -2,7 +2,6 @@ test_description='wildmatch tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh should_create_test_file() { diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index 436de44971..8f294d9832 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -17,7 +17,6 @@ The new path restriction code should do the right thing for path2 and path2/baz. Also path0/ should snow nothing. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success \ diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 5af2dac0e4..ac44525810 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -20,7 +20,6 @@ Test the handling of multiple directories which have matching file entries. Also test odd filename and missing entries handling. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh index 3942db2290..1e16c6b8ea 100755 --- a/t/t3102-ls-tree-wildcards.sh +++ b/t/t3102-ls-tree-wildcards.sh @@ -2,7 +2,6 @@ test_description='ls-tree with(out) globs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh index 81c6343962..e7636f6908 100755 --- a/t/t3103-ls-tree-misc.sh +++ b/t/t3103-ls-tree-misc.sh @@ -7,7 +7,6 @@ Miscellaneous tests for git ls-tree. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3104-ls-tree-format.sh b/t/t3104-ls-tree-format.sh index 3adb206a93..a1b2069a25 100755 --- a/t/t3104-ls-tree-format.sh +++ b/t/t3104-ls-tree-format.sh @@ -2,7 +2,6 @@ test_description='ls-tree --format' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-t3100.sh diff --git a/t/t3105-ls-tree-output.sh b/t/t3105-ls-tree-output.sh index ce2391e28b..8bdf400682 100755 --- a/t/t3105-ls-tree-output.sh +++ b/t/t3105-ls-tree-output.sh @@ -2,7 +2,6 @@ test_description='ls-tree output' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-t3100.sh diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index ccfa6a720d..a3a21c54cf 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -8,7 +8,6 @@ test_description='git branch assorted tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh @@ -1697,7 +1696,7 @@ test_expect_success 'errors if given a bad branch name' ' cat <<-\EOF >expect && fatal: '\''foo..bar'\'' is not a valid branch name hint: See `man git check-ref-format` - hint: Disable this message with "git config advice.refSyntax false" + hint: Disable this message with "git config set advice.refSyntax false" EOF test_must_fail git branch foo..bar >actual 2>&1 && test_cmp expect actual diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh index 6e587d27d7..800fc33165 100755 --- a/t/t3201-branch-contains.sh +++ b/t/t3201-branch-contains.sh @@ -2,7 +2,6 @@ test_description='branch --contains <commit>, --no-contains <commit> --merged, and --no-merged' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index 3b6dad0c46..a1139f79e2 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -2,7 +2,6 @@ test_description='test show-branch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'error descriptions on empty repository' ' diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index e627f08a17..500c9d0e72 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -2,7 +2,6 @@ test_description='git branch display tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh diff --git a/t/t3204-branch-name-interpretation.sh b/t/t3204-branch-name-interpretation.sh index 594e3e43e1..3399344f25 100755 --- a/t/t3204-branch-name-interpretation.sh +++ b/t/t3204-branch-name-interpretation.sh @@ -9,7 +9,6 @@ This script aims to check the behavior of those corner cases. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh expect_branch() { diff --git a/t/t3205-branch-color.sh b/t/t3205-branch-color.sh index 0b61da92b3..da1c202fa7 100755 --- a/t/t3205-branch-color.sh +++ b/t/t3205-branch-color.sh @@ -1,7 +1,6 @@ #!/bin/sh test_description='basic branch output coloring' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up some sample branches' ' diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 973e20254b..d2ca43d6aa 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -5,7 +5,6 @@ test_description='range-diff tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Note that because of the range-diff's heuristics, test_commit does more @@ -534,9 +533,9 @@ test_expect_success 'dual-coloring' ' for prev in topic main..topic do test_expect_success "format-patch --range-diff=$prev" ' + test_when_finished "rm -f 000?-*" && git format-patch --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && @@ -561,32 +560,32 @@ test_expect_success "explicit --no-cover-letter defeats implied --cover-letter" ' test_expect_success 'format-patch --range-diff as commentary' ' + test_when_finished "rm -f 0001-*" && git format-patch --range-diff=HEAD~1 HEAD~1 >actual && - test_when_finished "rm 0001-*" && test_line_count = 1 actual && test_grep "^Range-diff:$" 0001-* && grep "> 1: .* new message" 0001-* ' test_expect_success 'format-patch --range-diff reroll-count with a non-integer' ' + test_when_finished "rm -f v2.9-0001-*" && git format-patch --range-diff=HEAD~1 -v2.9 HEAD~1 >actual && - test_when_finished "rm v2.9-0001-*" && test_line_count = 1 actual && test_grep "^Range-diff:$" v2.9-0001-* && grep "> 1: .* new message" v2.9-0001-* ' test_expect_success 'format-patch --range-diff reroll-count with a integer' ' + test_when_finished "rm -f v2-0001-*" && git format-patch --range-diff=HEAD~1 -v2 HEAD~1 >actual && - test_when_finished "rm v2-0001-*" && test_line_count = 1 actual && test_grep "^Range-diff ..* v1:$" v2-0001-* && grep "> 1: .* new message" v2-0001-* ' test_expect_success 'format-patch --range-diff with v0' ' + test_when_finished "rm -f v0-0001-*" && git format-patch --range-diff=HEAD~1 -v0 HEAD~1 >actual && - test_when_finished "rm v0-0001-*" && test_line_count = 1 actual && test_grep "^Range-diff:$" v0-0001-* && grep "> 1: .* new message" v0-0001-* @@ -607,9 +606,9 @@ test_expect_success 'basic with modified format.pretty without "commit "' ' ' test_expect_success 'range-diff compares notes by default' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && git range-diff --no-color main..topic main..unmodified \ >actual && sed s/Z/\ /g >expect <<-EOF && @@ -631,9 +630,9 @@ test_expect_success 'range-diff compares notes by default' ' ' test_expect_success 'range-diff with --no-notes' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && git range-diff --no-color --no-notes main..topic main..unmodified \ >actual && cat >expect <<-EOF && @@ -646,12 +645,12 @@ test_expect_success 'range-diff with --no-notes' ' ' test_expect_success 'range-diff with multiple --notes' ' + test_when_finished "git notes --ref=note1 remove topic unmodified || :" && git notes --ref=note1 add -m "topic note1" topic && git notes --ref=note1 add -m "unmodified note1" unmodified && - test_when_finished git notes --ref=note1 remove topic unmodified && + test_when_finished "git notes --ref=note2 remove topic unmodified || :" && git notes --ref=note2 add -m "topic note2" topic && git notes --ref=note2 add -m "unmodified note2" unmodified && - test_when_finished git notes --ref=note2 remove topic unmodified && git range-diff --no-color --notes=note1 --notes=note2 main..topic main..unmodified \ >actual && sed s/Z/\ /g >expect <<-EOF && @@ -679,12 +678,12 @@ test_expect_success 'range-diff with multiple --notes' ' # `range-diff` should act like `log` with regards to notes test_expect_success 'range-diff with --notes=custom does not show default notes' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && + test_when_finished "git notes --ref=custom remove topic unmodified || :" && git notes --ref=custom add -m "topic note" topic && git notes --ref=custom add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && - test_when_finished git notes --ref=custom remove topic unmodified && git range-diff --notes=custom main..topic main..unmodified \ >actual && ! grep "## Notes ##" actual && @@ -692,12 +691,12 @@ test_expect_success 'range-diff with --notes=custom does not show default notes' ' test_expect_success 'format-patch --range-diff does not compare notes by default' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && + test_when_finished "rm -f 000?-*" && git format-patch --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && @@ -709,26 +708,26 @@ test_expect_success 'format-patch --range-diff does not compare notes by default ' test_expect_success 'format-patch --notes=custom --range-diff only compares custom notes' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && - git notes --ref=custom add -m "topic note (custom)" topic && git notes add -m "unmodified note" unmodified && + test_when_finished "git notes --ref=custom remove topic unmodified || :" && + git notes --ref=custom add -m "topic note (custom)" topic && git notes --ref=custom add -m "unmodified note (custom)" unmodified && - test_when_finished git notes remove topic unmodified && - test_when_finished git notes --ref=custom remove topic unmodified && + test_when_finished "rm -f 000?-*" && git format-patch --notes=custom --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && grep "## Notes (custom) ##" 0000-* && ! grep "## Notes ##" 0000-* ' test_expect_success 'format-patch --range-diff with --no-notes' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && + test_when_finished "rm -f 000?-*" && git format-patch --no-notes --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && @@ -740,12 +739,12 @@ test_expect_success 'format-patch --range-diff with --no-notes' ' ' test_expect_success 'format-patch --range-diff with --notes' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && + test_when_finished "rm -f 000?-*" && git format-patch --notes --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && @@ -768,13 +767,13 @@ test_expect_success 'format-patch --range-diff with --notes' ' ' test_expect_success 'format-patch --range-diff with format.notes config' ' + test_when_finished "git notes remove topic unmodified || :" && git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && - test_when_finished git notes remove topic unmodified && test_config format.notes true && + test_when_finished "rm -f 000?-*" && git format-patch --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && @@ -797,15 +796,15 @@ test_expect_success 'format-patch --range-diff with format.notes config' ' ' test_expect_success 'format-patch --range-diff with multiple notes' ' + test_when_finished "git notes --ref=note1 remove topic unmodified || :" && git notes --ref=note1 add -m "topic note1" topic && git notes --ref=note1 add -m "unmodified note1" unmodified && - test_when_finished git notes --ref=note1 remove topic unmodified && + test_when_finished "git notes --ref=note2 remove topic unmodified || :" && git notes --ref=note2 add -m "topic note2" topic && git notes --ref=note2 add -m "unmodified note2" unmodified && - test_when_finished git notes --ref=note2 remove topic unmodified && + test_when_finished "rm -f 000?-*" && git format-patch --notes=note1 --notes=note2 --cover-letter --range-diff=$prev \ main..unmodified >actual && - test_when_finished "rm 000?-*" && test_line_count = 5 actual && test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh index 9cbc34fc58..37b9d26f4b 100755 --- a/t/t3211-peel-ref.sh +++ b/t/t3211-peel-ref.sh @@ -4,7 +4,6 @@ test_description='tests for the peel_ref optimization of packed-refs' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create annotated tag in refs/tags' ' diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index d3ac826283..f5bf16abcd 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -9,7 +9,6 @@ This test tries pathnames with funny characters in the working tree, index, and tree objects. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh HT=' ' diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 536bd11ff4..d6c50460d0 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -5,7 +5,6 @@ test_description='Test commit notes' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh write_script fake_editor <<\EOF @@ -1557,4 +1556,77 @@ test_expect_success 'empty notes are displayed by git log' ' test_cmp expect actual ' +test_expect_success 'empty notes do not invoke the editor' ' + test_commit 18th && + GIT_EDITOR="false" git notes add -C "$empty_blob" --allow-empty && + git notes remove HEAD && + GIT_EDITOR="false" git notes add -m "" --allow-empty && + git notes remove HEAD && + GIT_EDITOR="false" git notes add -F /dev/null --allow-empty && + git notes remove HEAD +' + +test_expect_success 'git notes add with -m/-F invokes editor with -e' ' + test_commit 19th && + echo "edited" >expect && + MSG="$(cat expect)" git notes add -m "initial" -e && + git notes show >actual && + test_cmp expect actual && + git notes remove HEAD && + + # Add a note using -F and edit it + echo "initial" >note_file && + MSG="$(cat expect)" git notes add -F note_file -e && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'git notes append with -m/-F invokes the editor with -e' ' + test_commit 20th && + cat >expect <<-EOF && + initial + + edited + EOF + git notes add -m "initial" && + MSG="edited" git notes append -m "appended" -e && + + # Verify the note content was appended and edited + git notes show >actual && + test_cmp expect actual && + git notes remove HEAD && + + # Append a note using -F and edit it + echo "note from file" >note_file && + git notes add -m "initial" && + MSG="edited" git notes append -F note_file -e && + + # Verify notes from file has been edited in editor and appended + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'git notes with a combination of -m, -F and -e invokes editor' ' + test_commit 21st && + echo "foo-file-1" >note_1 && + echo "foo-file-2" >note_2 && + echo "edited" >expect && + + MSG=$(cat expect) git notes append -F note_1 -m "message-1" -F note_2 -e && + + # Verify that combined messages from file and -m have been edited + git notes show >actual && + test_cmp expect actual +' +test_expect_success 'git notes append aborts when editor fails with -e' ' + test_commit 22nd && + echo "foo-file-1" >note_1 && + + # Try to append a note with -F and -e, but make the editor fail + test_env GIT_EDITOR="false" test_must_fail git notes append -F note_1 -e && + + # Verify that no note was added due to editor failure + test_must_fail git notes show +' + test_done diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh index d0c4d38b4d..bb5fea02a0 100755 --- a/t/t3302-notes-index-expensive.sh +++ b/t/t3302-notes-index-expensive.sh @@ -8,7 +8,6 @@ test_description='Test commit notes index (expensive!)' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh create_repo () { diff --git a/t/t3303-notes-subtrees.sh b/t/t3303-notes-subtrees.sh index bc9b791d1b..eac193757b 100755 --- a/t/t3303-notes-subtrees.sh +++ b/t/t3303-notes-subtrees.sh @@ -5,7 +5,6 @@ test_description='Test commit notes organized in subtrees' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh number_of_commits=100 diff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh index 2c3a245266..03dfcd3954 100755 --- a/t/t3304-notes-mixed.sh +++ b/t/t3304-notes-mixed.sh @@ -5,7 +5,6 @@ test_description='Test notes trees that also contain non-notes' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh number_of_commits=100 diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh index 1ec1fb6715..fcecdc94ff 100755 --- a/t/t3305-notes-fanout.sh +++ b/t/t3305-notes-fanout.sh @@ -2,7 +2,6 @@ test_description='Test that adding/removing many notes triggers automatic fanout restructuring' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh path_has_fanout() { diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh index b6e9f643e3..8f4102ff9e 100755 --- a/t/t3306-notes-prune.sh +++ b/t/t3306-notes-prune.sh @@ -2,7 +2,6 @@ test_description='Test git notes prune' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup: create a few commits with notes' ' diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh index ae316502c4..1aa366a410 100755 --- a/t/t3307-notes-man.sh +++ b/t/t3307-notes-man.sh @@ -4,7 +4,6 @@ test_description='Examples from the git-notes man page Make sure the manual is not full of lies.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3308-notes-merge.sh b/t/t3308-notes-merge.sh index e1d05ff6bc..202702be1a 100755 --- a/t/t3308-notes-merge.sh +++ b/t/t3308-notes-merge.sh @@ -5,7 +5,6 @@ test_description='Test merging of notes trees' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh index f55277f499..9bd5dbf341 100755 --- a/t/t3309-notes-merge-auto-resolve.sh +++ b/t/t3309-notes-merge-auto-resolve.sh @@ -5,7 +5,6 @@ test_description='Test notes merging with auto-resolving strategies' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Set up a notes merge scenario with all kinds of potential conflicts diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh index 0fd33280cf..96243b7222 100755 --- a/t/t3320-notes-merge-worktrees.sh +++ b/t/t3320-notes-merge-worktrees.sh @@ -8,7 +8,6 @@ test_description='Test merging of notes trees in multiple worktrees' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup commit' ' diff --git a/t/t3321-notes-stripspace.sh b/t/t3321-notes-stripspace.sh index beca346056..c4a7839540 100755 --- a/t/t3321-notes-stripspace.sh +++ b/t/t3321-notes-stripspace.sh @@ -5,7 +5,6 @@ test_description='Test commit notes with stripspace behavior' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh MULTI_LF="$LF$LF$LF" diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index ae34bfad60..c0c00fbb7b 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -11,7 +11,6 @@ among other things. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh GIT_AUTHOR_NAME=author@name @@ -145,7 +144,9 @@ test_expect_success 'Show verbose error when HEAD could not be detached' ' test_when_finished "rm -f B" && test_must_fail git rebase topic 2>output.err >output.out && test_grep "The following untracked working tree files would be overwritten by checkout:" output.err && - test_grep B output.err + test_grep B output.err && + test_must_fail git rebase --quit 2>err && + test_grep "no rebase in progress" err ' test_expect_success 'fail when upstream arg is missing and not on branch' ' @@ -235,6 +236,12 @@ test_expect_success 'rebase --merge -q is quiet' ' test_must_be_empty output.out ' +test_expect_success 'rebase --exec -q is quiet' ' + git checkout -B quiet topic && + git rebase --exec true -q main >output.out 2>&1 && + test_must_be_empty output.out +' + test_expect_success 'Rebase a commit that sprinkles CRs in' ' ( echo "One" && @@ -422,7 +429,9 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' ' git checkout main && git worktree add wt && test_must_fail git -C wt rebase main main 2>err && - test_grep "already used by worktree at" err + test_grep "already used by worktree at" err && + test_must_fail git -C wt rebase --quit 2>err && + test_grep "no rebase in progress" err ' test_expect_success 'rebase when inside worktree subdirectory' ' @@ -446,4 +455,23 @@ test_expect_success 'rebase when inside worktree subdirectory' ' ) ' +test_expect_success 'git rebase --update-ref with core.commentChar and branch on worktree' ' + test_when_finished git branch -D base topic2 && + test_when_finished git checkout main && + test_when_finished git branch -D wt-topic && + test_when_finished git worktree remove wt-topic && + git checkout main && + git checkout -b base && + git checkout -b topic2 && + test_commit msg2 && + git worktree add wt-topic && + git checkout base && + test_commit msg3 && + git checkout topic2 && + GIT_SEQUENCE_EDITOR="cat >actual" git -c core.commentChar=% \ + rebase -i --update-refs base && + test_grep "% Ref refs/heads/wt-topic checked out at" actual && + test_grep "% Ref refs/heads/topic2 checked out at" actual +' + test_done diff --git a/t/t3401-rebase-and-am-rename.sh b/t/t3401-rebase-and-am-rename.sh index 328c1d3a3f..f18bae9450 100755 --- a/t/t3401-rebase-and-am-rename.sh +++ b/t/t3401-rebase-and-am-rename.sh @@ -2,7 +2,6 @@ test_description='git rebase + directory rename tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index 5c67d07ba3..761de63b6b 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -8,7 +8,6 @@ test_description='git rebase --merge test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh T="A quick brown fox diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 4f1d6e8ea6..a1911c4a9d 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -8,7 +8,6 @@ test_description='git rebase --merge --skip tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index f92baad138..ecfc02062c 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -280,8 +280,9 @@ test_expect_success 'stop on conflicting pick' ' test_cmp expect2 file1 && test "$(git diff --name-status | sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 && - test 4 = $(grep -v "^#" < .git/rebase-merge/done | wc -l) && - test 0 = $(grep -c "^[^#]" < .git/rebase-merge/git-rebase-todo) + grep -v "^#" <.git/rebase-merge/done >actual && + test_line_count = 4 actual && + test 0 = $(grep -c "^[^#]" <.git/rebase-merge/git-rebase-todo) ' test_expect_success 'show conflicted patch' ' @@ -318,7 +319,8 @@ test_expect_success 'retain authorship' ' GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && git tag twerp && git rebase -i --onto primary HEAD^ && - git show HEAD | grep "^Author: Twerp Snog" + git show HEAD >actual && + grep "^Author: Twerp Snog" actual ' test_expect_success 'retain authorship w/ conflicts' ' @@ -359,7 +361,8 @@ test_expect_success 'squash' ' ' test_expect_success 'retain authorship when squashing' ' - git show HEAD | grep "^Author: Twerp Snog" + git show HEAD >actual && + grep "^Author: Twerp Snog" actual ' test_expect_success '--continue tries to commit' ' @@ -373,7 +376,8 @@ test_expect_success '--continue tries to commit' ' FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue ) && test_cmp_rev HEAD^ new-branch1 && - git show HEAD | grep chouette + git show HEAD >actual && + grep chouette actual ' test_expect_success 'verbose flag is heeded, even after --continue' ' @@ -396,7 +400,9 @@ test_expect_success 'multi-squash only fires up editor once' ' git rebase -i $base ) && test $base = $(git rev-parse HEAD^) && - test 1 = $(git show | grep ONCE | wc -l) + git show >output && + grep ONCE output >actual && + test_line_count = 1 actual ' test_expect_success 'multi-fixup does not fire up editor' ' @@ -409,7 +415,8 @@ test_expect_success 'multi-fixup does not fire up editor' ' git rebase -i $base ) && test $base = $(git rev-parse HEAD^) && - test 0 = $(git show | grep NEVER | wc -l) && + git show >output && + ! grep NEVER output && git checkout @{-1} && git branch -D multi-fixup ' @@ -427,7 +434,9 @@ test_expect_success 'commit message used after conflict' ' git rebase --continue ) && test $base = $(git rev-parse HEAD^) && - test 1 = $(git show | grep ONCE | wc -l) && + git show >output && + grep ONCE output >actual && + test_line_count = 1 actual && git checkout @{-1} && git branch -D conflict-fixup ' @@ -445,7 +454,9 @@ test_expect_success 'commit message retained after conflict' ' git rebase --continue ) && test $base = $(git rev-parse HEAD^) && - test 2 = $(git show | grep TWICE | wc -l) && + git show >output && + grep TWICE output >actual && + test_line_count = 2 actual && git checkout @{-1} && git branch -D conflict-squash ' @@ -469,10 +480,10 @@ test_expect_success 'squash and fixup generate correct log messages' ' ) && git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && test_cmp expect-squash-fixup actual-squash-fixup && - git cat-file commit HEAD@{2} | - grep "^# This is a combination of 3 commits\." && - git cat-file commit HEAD@{3} | - grep "^# This is a combination of 2 commits\." && + git cat-file commit HEAD@{2} >actual && + grep "^# This is a combination of 3 commits\." actual && + git cat-file commit HEAD@{3} >actual && + grep "^# This is a combination of 2 commits\." actual && git checkout @{-1} && git branch -D squash-fixup ' @@ -488,7 +499,9 @@ test_expect_success 'squash ignores comments' ' git rebase -i $base ) && test $base = $(git rev-parse HEAD^) && - test 1 = $(git show | grep ONCE | wc -l) && + git show >output && + grep ONCE output >actual && + test_line_count = 1 actual && git checkout @{-1} && git branch -D skip-comments ' @@ -504,7 +517,9 @@ test_expect_success 'squash ignores blank lines' ' git rebase -i $base ) && test $base = $(git rev-parse HEAD^) && - test 1 = $(git show | grep ONCE | wc -l) && + git show >output && + grep ONCE output >actual && + test_line_count = 1 actual && git checkout @{-1} && git branch -D skip-blank-lines ' @@ -571,7 +586,8 @@ test_expect_success '--continue tries to commit, even for "edit"' ' FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue ) && test edited = $(git show HEAD:file7) && - git show HEAD | grep chouette && + git show HEAD >actual && + grep chouette actual && test $parent = $(git rev-parse HEAD^) ' @@ -756,19 +772,23 @@ test_expect_success 'reword' ' set_fake_editor && FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" \ git rebase -i A && - git show HEAD | grep "E changed" && + git show HEAD >actual && + grep "E changed" actual && test $(git rev-parse primary) != $(git rev-parse HEAD) && test_cmp_rev primary^ HEAD^ && FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \ git rebase -i A && - git show HEAD^ | grep "D changed" && + git show HEAD^ >actual && + grep "D changed" actual && FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" \ git rebase -i A && - git show HEAD~3 | grep "B changed" && + git show HEAD~3 >actual && + grep "B changed" actual && FAKE_LINES="1 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" \ git rebase -i A ) && - git show HEAD~2 | grep "C changed" + git show HEAD~2 >actual && + grep "C changed" actual ' test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' ' @@ -1002,8 +1022,10 @@ test_expect_success 'rebase -i --root retain root commit author and message' ' set_fake_editor && FAKE_LINES="2" git rebase -i --root ) && - git cat-file commit HEAD | grep -q "^author Twerp Snog" && - git cat-file commit HEAD | grep -q "^different author$" + git cat-file commit HEAD >output && + grep -q "^author Twerp Snog" output && + git cat-file commit HEAD >actual && + grep -q "^different author$" actual ' test_expect_success 'rebase -i --root temporary sentinel commit' ' @@ -1012,7 +1034,8 @@ test_expect_success 'rebase -i --root temporary sentinel commit' ' set_fake_editor && test_must_fail env FAKE_LINES="2" git rebase -i --root ) && - git cat-file commit HEAD | grep "^tree $EMPTY_TREE" && + git cat-file commit HEAD >actual && + grep "^tree $EMPTY_TREE" actual && git rebase --abort ' @@ -1035,7 +1058,8 @@ test_expect_success 'rebase -i --root reword original root commit' ' FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \ git rebase -i --root ) && - git show HEAD^ | grep "A changed" && + git show HEAD^ >actual && + grep "A changed" actual && test -z "$(git show -s --format=%p HEAD^)" ' @@ -1047,7 +1071,8 @@ test_expect_success 'rebase -i --root reword new root commit' ' FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \ git rebase -i --root ) && - git show HEAD^ | grep "C changed" && + git show HEAD^ >actual && + grep "C changed" actual && test -z "$(git show -s --format=%p HEAD^)" ' @@ -1869,7 +1894,7 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' pick $(git log -1 --format=%h branch2~1) F pick $(git log -1 --format=%h branch2) I update-ref refs/heads/branch2 - label merge + label branch2 reset onto pick $(git log -1 --format=%h refs/heads/second) J update-ref refs/heads/second @@ -1880,7 +1905,7 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' update-ref refs/heads/third pick $(git log -1 --format=%h HEAD~2) M update-ref refs/heads/no-conflict-branch - merge -C $(git log -1 --format=%h HEAD~1) merge # merge + merge -C $(git log -1 --format=%h HEAD~1) branch2 # merge update-ref refs/heads/merge-branch EOF @@ -1916,18 +1941,17 @@ test_expect_success '--update-refs updates refs correctly' ' test_cmp_rev HEAD~1 refs/heads/third && test_cmp_rev HEAD refs/heads/no-conflict-branch && - cat >expect <<-\EOF && + q_to_tab >expect <<-\EOF && Successfully rebased and updated refs/heads/update-refs. Updated the following refs with --update-refs: - refs/heads/first - refs/heads/no-conflict-branch - refs/heads/second - refs/heads/third + Qrefs/heads/first + Qrefs/heads/no-conflict-branch + Qrefs/heads/second + Qrefs/heads/third EOF # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. - sed -e "s/Rebasing.*Successfully/Successfully/g" -e "s/^\t//g" \ - <err >err.trimmed && + sed "s/Rebasing.*Successfully/Successfully/g" <err >err.trimmed && test_cmp expect err.trimmed ' @@ -2177,19 +2201,18 @@ test_expect_success '--update-refs: check failed ref update' ' test_must_fail git rebase --continue 2>err && grep "update_ref failed for ref '\''refs/heads/second'\''" err && - cat >expect <<-\EOF && + q_to_tab >expect <<-\EOF && Updated the following refs with --update-refs: - refs/heads/first - refs/heads/no-conflict-branch - refs/heads/third + Qrefs/heads/first + Qrefs/heads/no-conflict-branch + Qrefs/heads/third Failed to update the following refs with --update-refs: - refs/heads/second + Qrefs/heads/second EOF # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. tail -n 6 err >err.last && - sed -e "s/Rebasing.*Successfully/Successfully/g" -e "s/^\t//g" \ - <err.last >err.trimmed && + sed "s/Rebasing.*Successfully/Successfully/g" <err.last >err.trimmed && test_cmp expect err.trimmed ' @@ -2235,20 +2258,20 @@ test_expect_success 'non-merge commands reject merge commits' ' error: ${SQ}pick${SQ} does not accept merge commits hint: ${SQ}pick${SQ} does not take a merge commit. If you wanted to hint: replay the merge, use ${SQ}merge -C${SQ} on the commit. - hint: Disable this message with "git config advice.rebaseTodoError false" + hint: Disable this message with "git config set advice.rebaseTodoError false" error: invalid line 1: pick $oid error: ${SQ}reword${SQ} does not accept merge commits hint: ${SQ}reword${SQ} does not take a merge commit. If you wanted to hint: replay the merge and reword the commit message, use hint: ${SQ}merge -c${SQ} on the commit - hint: Disable this message with "git config advice.rebaseTodoError false" + hint: Disable this message with "git config set advice.rebaseTodoError false" error: invalid line 2: reword $oid error: ${SQ}edit${SQ} does not accept merge commits hint: ${SQ}edit${SQ} does not take a merge commit. If you wanted to hint: replay the merge, use ${SQ}merge -C${SQ} on the commit, and then hint: ${SQ}break${SQ} to give the control back to you so that you can hint: do ${SQ}git commit --amend && git rebase --continue${SQ}. - hint: Disable this message with "git config advice.rebaseTodoError false" + hint: Disable this message with "git config set advice.rebaseTodoError false" error: invalid line 3: edit $oid error: cannot squash merge commit into another commit error: invalid line 4: fixup $oid diff --git a/t/t3405-rebase-malformed.sh b/t/t3405-rebase-malformed.sh index 8979bc3407..2524331861 100755 --- a/t/t3405-rebase-malformed.sh +++ b/t/t3405-rebase-malformed.sh @@ -5,7 +5,6 @@ test_description='rebase should handle arbitrary git message' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index 82108b67e6..a1d7fa7f7c 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -5,7 +5,6 @@ test_description='messages from rebase operation' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh index 2c3f38d45a..9f49c4228b 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -5,7 +5,6 @@ test_description='git rebase --abort tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh index 7b4607d72f..cde3562e3a 100755 --- a/t/t3408-rebase-multi-line.sh +++ b/t/t3408-rebase-multi-line.sh @@ -5,7 +5,6 @@ test_description='rebasing a commit with multi-line first paragraph.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3409-rebase-environ.sh b/t/t3409-rebase-environ.sh index acaf5558db..83ffb39d9f 100755 --- a/t/t3409-rebase-environ.sh +++ b/t/t3409-rebase-environ.sh @@ -2,7 +2,6 @@ test_description='git rebase interactive environment' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh index e75b3d0e07..58371d8a54 100755 --- a/t/t3412-rebase-root.sh +++ b/t/t3412-rebase-root.sh @@ -7,7 +7,6 @@ Tests if git rebase --root --onto <newparent> can rebase the root commit. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh log_with_names () { diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh index e8456831e8..b4ff614987 100755 --- a/t/t3413-rebase-hook.sh +++ b/t/t3413-rebase-hook.sh @@ -5,7 +5,6 @@ test_description='git rebase with its hook(s)' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -110,7 +109,9 @@ test_expect_success 'pre-rebase hook stops rebase (1)' ' git reset --hard side && test_must_fail git rebase main && test "z$(git symbolic-ref HEAD)" = zrefs/heads/test && - test 0 = $(git rev-list HEAD...side | wc -l) + test 0 = $(git rev-list HEAD...side | wc -l) && + test_must_fail git rebase --quit 2>err && + test_grep "no rebase in progress" err ' test_expect_success 'pre-rebase hook stops rebase (2)' ' diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 22452ff84c..fcc40d6fe1 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -5,7 +5,6 @@ test_description='auto squash' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh index f8c4ed78c9..ea501f2b42 100755 --- a/t/t3416-rebase-onto-threedots.sh +++ b/t/t3416-rebase-onto-threedots.sh @@ -5,7 +5,6 @@ test_description='git rebase --onto A...B' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-rebase.sh" diff --git a/t/t3417-rebase-whitespace-fix.sh b/t/t3417-rebase-whitespace-fix.sh index 22ee3a2045..96f2cf22fa 100755 --- a/t/t3417-rebase-whitespace-fix.sh +++ b/t/t3417-rebase-whitespace-fix.sh @@ -5,7 +5,6 @@ test_description='git rebase --whitespace=fix This test runs git rebase --whitespace=fix and make sure that it works. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # prepare initial revision of "file" with a blank line at the end diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index c0d29c2154..127216f722 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -5,7 +5,6 @@ test_description='git rebase --continue tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh index 6c61f240cf..7181f176b8 100755 --- a/t/t3419-rebase-patch-id.sh +++ b/t/t3419-rebase-patch-id.sh @@ -5,7 +5,6 @@ test_description='git rebase - test patch id computation' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh scramble () { diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 63e400b89f..ad3ba6a984 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -7,7 +7,6 @@ test_description='git rebase --autostash tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -82,6 +81,46 @@ testrebase () { type=$1 dotest=$2 + test_expect_success "rebase$type: restore autostash when pre-rebase hook fails" ' + git checkout -f feature-branch && + test_hook pre-rebase <<-\EOF && + exit 1 + EOF + + echo changed >file0 && + test_must_fail git rebase $type --autostash -f HEAD^ && + test_must_fail git rebase --quit 2>err && + test_grep "no rebase in progress" err && + echo changed >expect && + test_cmp expect file0 + ' + + test_expect_success "rebase$type: restore autostash when checkout onto fails" ' + git checkout -f --detach feature-branch && + echo uncommitted-content >file0 && + echo untracked >file4 && + test_when_finished "rm file4" && + test_must_fail git rebase $type --autostash \ + unrelated-onto-branch && + test_must_fail git rebase --quit 2>err && + test_grep "no rebase in progress" err && + echo uncommitted-content >expect && + test_cmp expect file0 + ' + + test_expect_success "rebase$type: restore autostash when branch checkout fails" ' + git checkout -f unrelated-onto-branch^ && + echo uncommitted-content >file0 && + echo untracked >file4 && + test_when_finished "rm file4" && + test_must_fail git rebase $type --autostash HEAD \ + unrelated-onto-branch && + test_must_fail git rebase --quit 2>err && + test_grep "no rebase in progress" err && + echo uncommitted-content >expect && + test_cmp expect file0 + ' + test_expect_success "rebase$type: dirty worktree, --no-autostash" ' test_config rebase.autostash true && git reset --hard && diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh index 737af80bb3..f5b7807abd 100755 --- a/t/t3421-rebase-topology-linear.sh +++ b/t/t3421-rebase-topology-linear.sh @@ -2,7 +2,6 @@ test_description='basic rebase topology tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh index b40f26250b..b9408f9ba1 100755 --- a/t/t3422-rebase-incompatible-options.sh +++ b/t/t3422-rebase-incompatible-options.sh @@ -2,7 +2,6 @@ test_description='test if rebase detects and aborts on incompatible options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3423-rebase-reword.sh b/t/t3423-rebase-reword.sh index 2fab703d61..4859bb8f72 100755 --- a/t/t3423-rebase-reword.sh +++ b/t/t3423-rebase-reword.sh @@ -2,7 +2,6 @@ test_description='git rebase interactive with rewording' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3424-rebase-empty.sh b/t/t3424-rebase-empty.sh index 515c949ae3..1ee6b00fd5 100755 --- a/t/t3424-rebase-empty.sh +++ b/t/t3424-rebase-empty.sh @@ -2,7 +2,6 @@ test_description='git rebase of commits that start or become empty' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup test repository' ' diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh index a16428bdf5..675491234a 100755 --- a/t/t3425-rebase-topology-merges.sh +++ b/t/t3425-rebase-topology-merges.sh @@ -2,7 +2,6 @@ test_description='rebase topology tests with merges' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3426-rebase-submodule.sh b/t/t3426-rebase-submodule.sh index 94ea88e384..ba069dccbd 100755 --- a/t/t3426-rebase-submodule.sh +++ b/t/t3426-rebase-submodule.sh @@ -2,7 +2,6 @@ test_description='rebase can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh index 365436ebfc..6f57aed9fa 100755 --- a/t/t3428-rebase-signoff.sh +++ b/t/t3428-rebase-signoff.sh @@ -5,7 +5,6 @@ test_description='git rebase --signoff This test runs git rebase --signoff and make sure that it works. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh index 8e0d03969a..abd66f3602 100755 --- a/t/t3429-rebase-edit-todo.sh +++ b/t/t3429-rebase-edit-todo.sh @@ -2,7 +2,6 @@ test_description='rebase should reread the todo file if an exec modifies it' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index 36ca126bcd..2593711fec 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -21,7 +21,6 @@ Initial setup: GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh . "$TEST_DIRECTORY"/lib-log-graph.sh @@ -108,19 +107,19 @@ test_expect_success 'generate correct todo list' ' reset onto pick $b B - label E + label first reset onto pick $c C label branch-point pick $f F pick $g G - label H + label second reset branch-point # C pick $d D - merge -C $e E # E - merge -C $h H # H + merge -C $e first # E + merge -C $h second # H EOF @@ -392,8 +391,7 @@ test_expect_success 'refuse to merge ancestors of HEAD' ' test_expect_success 'root commits' ' git checkout --orphan unrelated && - (GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \ - test_commit second-root) && + test_commit --author "Parsnip <root@example.com>" second-root && test_commit third-root && cat >script-from-scratch <<-\EOF && pick third-root @@ -463,11 +461,11 @@ test_expect_success 'A root commit can be a cousin, treat it that way' ' ' test_expect_success 'labels that are object IDs are rewritten' ' - git checkout -b third B && + git checkout --detach B && test_commit I && third=$(git rev-parse HEAD) && git checkout -b labels main && - git merge --no-commit third && + git merge --no-commit $third && test_tick && git commit -m "Merge commit '\''$third'\'' into labels" && echo noop >script-from-scratch && diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh index 0bb284d61d..be09fc78c1 100755 --- a/t/t3431-rebase-fork-point.sh +++ b/t/t3431-rebase-fork-point.sh @@ -8,7 +8,6 @@ test_description='git rebase --fork-point test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # A---B---D---E (main) @@ -74,7 +73,7 @@ test_rebase 'G F C D B A' --onto D main test_rebase 'G F C B A' --keep-base refs/heads/main test_rebase 'G F C B A' --keep-base main -test_expect_success 'git rebase --fork-point with ambigous refname' ' +test_expect_success 'git rebase --fork-point with ambiguous refname' ' git checkout main && git checkout -b one && git checkout side && diff --git a/t/t3432-rebase-fast-forward.sh b/t/t3432-rebase-fast-forward.sh index 7f1a5dd3de..5086e14c02 100755 --- a/t/t3432-rebase-fast-forward.sh +++ b/t/t3432-rebase-fast-forward.sh @@ -8,7 +8,6 @@ test_description='ensure rebase fast-forwards commits when possible' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3433-rebase-across-mode-change.sh b/t/t3433-rebase-across-mode-change.sh index c8172b0852..05df964670 100755 --- a/t/t3433-rebase-across-mode-change.sh +++ b/t/t3433-rebase-across-mode-change.sh @@ -2,7 +2,6 @@ test_description='git rebase across mode change' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3434-rebase-i18n.sh b/t/t3434-rebase-i18n.sh index 26a48d6b10..8c94fdffc4 100755 --- a/t/t3434-rebase-i18n.sh +++ b/t/t3434-rebase-i18n.sh @@ -17,9 +17,14 @@ Initial setup: GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +if ! test_have_prereq ICONV +then + skip_all='skipping rebase i18n tests; iconv not available' + test_done +fi + compare_msg () { iconv -f "$2" -t "$3" "$TEST_DIRECTORY/t3434/$1" >expect && git cat-file commit HEAD >raw && diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh index 7929e2e2e3..5d306a4769 100755 --- a/t/t3437-rebase-fixup-options.sh +++ b/t/t3437-rebase-fixup-options.sh @@ -14,7 +14,6 @@ to the "fixup" command that works with "fixup!", "fixup -C" works with "amend!" upon --autosquash. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh @@ -127,6 +126,21 @@ test_expect_success 'fixup -C with conflicts gives correct message' ' test_cmp expected-author actual-author ' +test_expect_success 'conflicting fixup -C after fixup with custom comment string' ' + test_config core.commentString COMMENT && + test_when_finished "test_might_fail git rebase --abort" && + git checkout --detach A3 && + test_must_fail env FAKE_LINES="1 fixup 2 fixup_-C 4" git rebase -i A && + echo resolved >A && + git add A && + FAKE_COMMIT_AMEND=edited git rebase --continue && + test_commit_message HEAD <<-\EOF + A3 + + edited + EOF +' + test_expect_success 'skipping fixup -C after fixup gives correct message' ' test_when_finished "test_might_fail git rebase --abort" && git checkout --detach A3 && diff --git a/t/t3438-rebase-broken-files.sh b/t/t3438-rebase-broken-files.sh index 821f08e5af..78d42f4c79 100755 --- a/t/t3438-rebase-broken-files.sh +++ b/t/t3438-rebase-broken-files.sh @@ -2,7 +2,6 @@ test_description='rebase behavior when on-disk files are broken' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up conflicting branches' ' diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh index 61ca87512d..78c3eac54b 100755 --- a/t/t3500-cherry.sh +++ b/t/t3500-cherry.sh @@ -11,7 +11,6 @@ checks that git cherry only returns the second patch in the local branch GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh GIT_AUTHOR_EMAIL=bogus_email_address diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 411027fb58..8025a28cfd 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -5,7 +5,6 @@ test_description='miscellaneous basic tests for cherry-pick and revert' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -178,7 +177,7 @@ test_expect_success 'advice from failed revert' ' hint: You can instead skip this commit with "git revert --skip". hint: To abort and get back to the state before "git revert", hint: run "git revert --abort". - hint: Disable this message with "git config advice.mergeConflict false" + hint: Disable this message with "git config set advice.mergeConflict false" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual && @@ -228,6 +227,20 @@ test_expect_success 'identification of reverted commit (--reference)' ' test_cmp expect actual ' +test_expect_success 'git revert --reference with core.commentChar' ' + test_when_finished "git reset --hard to-ident" && + git checkout --detach to-ident && + GIT_EDITOR="head -n4 >actual" git -c core.commentChar=% revert \ + --edit --reference HEAD && + cat <<-EOF >expect && + % *** SAY WHY WE ARE REVERTING ON THE TITLE LINE *** + + This reverts commit $(git show -s --pretty=reference HEAD^). + + EOF + test_cmp expect actual +' + test_expect_success 'identification of reverted commit (revert.reference)' ' git checkout --detach to-ident && git -c revert.reference=true revert --no-edit HEAD && diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh index 1b2c0d6aca..5495eacfec 100755 --- a/t/t3502-cherry-pick-merge.sh +++ b/t/t3502-cherry-pick-merge.sh @@ -11,7 +11,6 @@ test_description='cherry picking and reverting a merge GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh index 76d393dc8a..95fe4feaee 100755 --- a/t/t3503-cherry-pick-root.sh +++ b/t/t3503-cherry-pick-root.sh @@ -5,7 +5,6 @@ test_description='test cherry-picking (and reverting) a root commit' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh index 597c98e9c5..18aeba161c 100755 --- a/t/t3504-cherry-pick-rerere.sh +++ b/t/t3504-cherry-pick-rerere.sh @@ -5,7 +5,6 @@ test_description='cherry-pick should rerere for conflicts' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -43,7 +42,7 @@ test_expect_success 'cherry-pick conflict with --rerere-autoupdate' ' git reset --hard bar-dev ' -test_expect_success 'cherry-pick conflict repsects rerere.autoUpdate' ' +test_expect_success 'cherry-pick conflict respects rerere.autoUpdate' ' test_config rerere.autoUpdate true && test_must_fail git cherry-pick foo..bar-main && test_cmp foo-expect foo && diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh index ead3fb4680..9748443530 100755 --- a/t/t3505-cherry-pick-empty.sh +++ b/t/t3505-cherry-pick-empty.sh @@ -5,7 +5,6 @@ test_description='test cherry-picking an empty commit' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh index b71bad17b8..7e11bd4a4c 100755 --- a/t/t3506-cherry-pick-ff.sh +++ b/t/t3506-cherry-pick-ff.sh @@ -5,7 +5,6 @@ test_description='test cherry-picking with --ff option' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index f3947b400a..44596cb1e8 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -34,7 +34,7 @@ test_expect_success setup ' git commit --allow-empty --allow-empty-message && git tag empty && git checkout main && - git config advice.detachedhead false + git config set advice.detachedhead false ' @@ -60,7 +60,7 @@ test_expect_success 'advice from failed cherry-pick' ' hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". - hint: Disable this message with "git config advice.mergeConflict false" + hint: Disable this message with "git config set advice.mergeConflict false" EOF test_must_fail git cherry-pick picked 2>actual && @@ -75,7 +75,7 @@ test_expect_success 'advice from failed cherry-pick --no-commit' " error: could not apply \$picked... picked hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' - hint: Disable this message with \"git config advice.mergeConflict false\" + hint: Disable this message with \"git config set advice.mergeConflict false\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual && diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh index afa7727a4a..2d53ce754c 100755 --- a/t/t3508-cherry-pick-many-commits.sh +++ b/t/t3508-cherry-pick-many-commits.sh @@ -5,7 +5,6 @@ test_description='test cherry-picking many commits' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_head_differs_from() { diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh index 171cc6d76b..f4159246e1 100755 --- a/t/t3509-cherry-pick-merge-df.sh +++ b/t/t3509-cherry-pick-merge-df.sh @@ -4,7 +4,6 @@ test_description='Test cherry-pick with directory/file conflicts' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'Initialize repository' ' diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 7eb52b12ed..66ff9db270 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -25,7 +25,7 @@ pristine_detach () { } test_expect_success setup ' - git config advice.detachedhead false && + git config set advice.detachedhead false && echo unrelated >unrelated && git add unrelated && test_commit initial foo a && diff --git a/t/t3511-cherry-pick-x.sh b/t/t3511-cherry-pick-x.sh index dd5d92ef30..98ef13f0a3 100755 --- a/t/t3511-cherry-pick-x.sh +++ b/t/t3511-cherry-pick-x.sh @@ -2,7 +2,6 @@ test_description='Test cherry-pick -x and -s' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pristine_detach () { @@ -52,7 +51,7 @@ trailing empty lines " test_expect_success setup ' - git config advice.detachedhead false && + git config set advice.detachedhead false && echo unrelated >unrelated && git add unrelated && test_commit initial foo a && diff --git a/t/t3512-cherry-pick-submodule.sh b/t/t3512-cherry-pick-submodule.sh index 9387a22a9e..f22d1ddead 100755 --- a/t/t3512-cherry-pick-submodule.sh +++ b/t/t3512-cherry-pick-submodule.sh @@ -5,7 +5,6 @@ test_description='cherry-pick can handle submodules' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t3513-revert-submodule.sh b/t/t3513-revert-submodule.sh index e178968b40..8bfe3ed246 100755 --- a/t/t3513-revert-submodule.sh +++ b/t/t3513-revert-submodule.sh @@ -2,7 +2,6 @@ test_description='revert can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 31ac31d4bc..98259e2ada 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -8,7 +8,6 @@ test_description='Test of the various options to git rm.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Setup some files to be removed, some with funny characters diff --git a/t/t3601-rm-pathspec-file.sh b/t/t3601-rm-pathspec-file.sh index 7cef12981c..31bd9960fc 100755 --- a/t/t3601-rm-pathspec-file.sh +++ b/t/t3601-rm-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='rm --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t3602-rm-sparse-checkout.sh b/t/t3602-rm-sparse-checkout.sh index fcdefba48c..02c7acd617 100755 --- a/t/t3602-rm-sparse-checkout.sh +++ b/t/t3602-rm-sparse-checkout.sh @@ -2,7 +2,6 @@ test_description='git rm in sparse checked out working trees' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' " @@ -21,7 +20,7 @@ test_expect_success 'setup' " hint: If you intend to update such entries, try one of the following: hint: * Use the --sparse option. hint: * Disable or modify the sparsity rules. - hint: Disable this message with \"git config advice.updateSparsePath false\" + hint: Disable this message with \"git config set advice.updateSparsePath false\" EOF echo b | cat sparse_error_header - >sparse_entry_b_error && diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 12bd3db4cb..389670262e 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -5,7 +5,6 @@ test_description='basic git replay tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh GIT_AUTHOR_NAME=author@name diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 839c904745..df580a5806 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -5,7 +5,6 @@ test_description='Test of git add, including the -- option.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-unique-files.sh @@ -32,7 +31,7 @@ test_expect_success 'Test with no pathspecs' ' cat >expect <<-EOF && Nothing specified, nothing added. hint: Maybe you wanted to say ${SQ}git add .${SQ}? - hint: Disable this message with "git config advice.addEmptyPathspec false" + hint: Disable this message with "git config set advice.addEmptyPathspec false" EOF git add 2>actual && test_cmp expect actual @@ -376,7 +375,7 @@ test_expect_success '"git add" a embedded repository' ' hint: git rm --cached inner1 hint: hint: See "git help submodule" for more information. - hint: Disable this message with "git config advice.addEmbeddedRepo false" + hint: Disable this message with "git config set advice.addEmbeddedRepo false" warning: adding embedded git repository: inner2 EOF test_cmp expect actual @@ -414,7 +413,7 @@ cat >expect.err <<\EOF The following paths are ignored by one of your .gitignore files: ignored-file hint: Use -f if you really want to add them. -hint: Disable this message with "git config advice.addIgnoredFile false" +hint: Disable this message with "git config set advice.addIgnoredFile false" EOF cat >expect.out <<\EOF add 'track-this' diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 5d78868ac1..b8a05d95f3 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -4,7 +4,6 @@ test_description='add -i basic tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -575,6 +574,54 @@ test_expect_success 'navigate to hunk via regex / pattern' ' test_cmp expect actual.trimmed ' +test_expect_success 'print again the hunk' ' + test_when_finished "git reset" && + tr _ " " >expect <<-EOF && + +15 + 20 + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? @@ -1,2 +1,3 @@ + 10 + +15 + 20 + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_ + EOF + test_write_lines s y g 1 p | git add -p >actual && + tail -n 7 <actual >actual.trimmed && + test_cmp expect actual.trimmed +' + +test_expect_success TTY 'print again the hunk (PAGER)' ' + test_when_finished "git reset" && + cat >expect <<-EOF && + <GREEN>+<RESET><GREEN>15<RESET> + 20<RESET> + <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET> + PAGER 10<RESET> + PAGER <GREEN>+<RESET><GREEN>15<RESET> + PAGER 20<RESET> + <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET> + EOF + test_write_lines s y g 1 P | + ( + GIT_PAGER="sed s/^/PAGER\ /" && + export GIT_PAGER && + test_terminal git add -p >actual + ) && + tail -n 7 <actual | test_decode_color >actual.trimmed && + test_cmp expect actual.trimmed +' + +test_expect_success TTY 'P handles SIGPIPE when writing to pager' ' + test_when_finished "rm -f huge_file; git reset" && + printf "\n%2500000s" Y >huge_file && + git add -N huge_file && + test_write_lines P q | ( + GIT_PAGER="head -n 1" && + export GIT_PAGER && + test_terminal git add -p + ) +' + test_expect_success 'split hunk "add -p (edit)"' ' # Split, say Edit and do nothing. Then: # @@ -1164,4 +1211,23 @@ test_expect_success 'reset -p with unmerged files' ' test_must_be_empty staged ' +test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' + test_config diff.suppressBlankEmpty true && + write_script fake-editor.sh <<-\EOF && + tr F G <"$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + + test_write_lines a b "" c d "" e f "" >file && + git add file && + test_write_lines A b "" c D "" e F "" >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && + test_write_lines s n y e q | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b "" c D "" e G "" >expect && + test_cmp expect actual +' + test_done diff --git a/t/t3702-add-edit.sh b/t/t3702-add-edit.sh index 82bfb2fd2a..8bacacbac6 100755 --- a/t/t3702-add-edit.sh +++ b/t/t3702-add-edit.sh @@ -5,7 +5,6 @@ test_description='add -e basic tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t3703-add-magic-pathspec.sh b/t/t3703-add-magic-pathspec.sh index d84071038e..3ef525a559 100755 --- a/t/t3703-add-magic-pathspec.sh +++ b/t/t3703-add-magic-pathspec.sh @@ -2,7 +2,6 @@ test_description='magic pathspec tests using git-add' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3704-add-pathspec-file.sh b/t/t3704-add-pathspec-file.sh index 3aa59f6f63..b9c96e273f 100755 --- a/t/t3704-add-pathspec-file.sh +++ b/t/t3704-add-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='add --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh index 2bade9e804..53a4782267 100755 --- a/t/t3705-add-sparse-checkout.sh +++ b/t/t3705-add-sparse-checkout.sh @@ -54,7 +54,7 @@ test_expect_success 'setup' " hint: If you intend to update such entries, try one of the following: hint: * Use the --sparse option. hint: * Disable or modify the sparsity rules. - hint: Disable this message with \"git config advice.updateSparsePath false\" + hint: Disable this message with \"git config set advice.updateSparsePath false\" EOF echo sparse_entry | cat sparse_error_header - >sparse_entry_error && diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index d3e428ff46..e3cf0ffbe5 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -4,7 +4,6 @@ test_description='git mktag: tag object verify test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh ########################################################### diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index db7b403bc1..3c930ec202 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -5,9 +5,14 @@ test_description='commit and log output encodings' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +if ! test_have_prereq ICONV +then + skip_all='skipping commit i18n tests; iconv not available' + test_done +fi + compare_with () { git show -s $1 | sed -e '1,/^$/d' -e 's/^ //' >current && case "$3" in diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh index 5f0b9afc3f..f03601b49a 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -8,9 +8,14 @@ test_description='i18n settings and format-patch | am pipe' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +if ! test_have_prereq ICONV +then + skip_all='skipping patch i18n tests; iconv not available' + test_done +fi + check_encoding () { # Make sure characters are not corrupted cnt="$1" header="$2" i=1 j=0 diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh index 72a5a565e9..f528008c36 100755 --- a/t/t3902-quoted.sh +++ b/t/t3902-quoted.sh @@ -5,7 +5,6 @@ test_description='quoted output' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh FN='濱野' diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index e4c0937f61..74666ff3e4 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -8,7 +8,6 @@ test_description='Test git stash' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-unique-files.sh @@ -1398,6 +1397,21 @@ test_expect_success 'stash --keep-index with file deleted in index does not resu test_path_is_missing to-remove ' +test_expect_success 'stash --keep-index --include-untracked with empty tree' ' + test_when_finished "rm -rf empty" && + git init empty && + ( + cd empty && + git commit --allow-empty --message "empty" && + echo content >file && + git stash push --keep-index --include-untracked && + test_path_is_missing file && + git stash pop && + echo content >expect && + test_cmp expect file + ) +' + test_expect_success 'stash apply should succeed with unmodified file' ' echo base >file && git add file && diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index aa5019fd6c..ae313e3c70 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -2,7 +2,6 @@ test_description='stash -p' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh test_expect_success 'setup' ' diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh index a1733f45c3..1289ae3e07 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -5,7 +5,6 @@ test_description='Test git stash --include-untracked' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'stash save --include-untracked some dirty working directory' ' diff --git a/t/t3906-stash-submodule.sh b/t/t3906-stash-submodule.sh index 0f61f01ef4..0f7348ec21 100755 --- a/t/t3906-stash-submodule.sh +++ b/t/t3906-stash-submodule.sh @@ -2,7 +2,6 @@ test_description='stash can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t3907-stash-show-config.sh b/t/t3907-stash-show-config.sh index 7a2eb98b86..10914bba7b 100755 --- a/t/t3907-stash-show-config.sh +++ b/t/t3907-stash-show-config.sh @@ -2,7 +2,6 @@ test_description='Test git stash show configuration.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3908-stash-in-worktree.sh b/t/t3908-stash-in-worktree.sh index 347a89b030..2b2b366ef9 100755 --- a/t/t3908-stash-in-worktree.sh +++ b/t/t3908-stash-in-worktree.sh @@ -5,7 +5,6 @@ test_description='Test git stash in a worktree' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh index 50ae222f08..e2e1251a05 100755 --- a/t/t3920-crlf-messages.sh +++ b/t/t3920-crlf-messages.sh @@ -2,7 +2,6 @@ test_description='Test ref-filter and pretty APIs for commit and tag messages using CRLF' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh LIB_CRLF_BRANCHES="" @@ -82,7 +81,7 @@ test_crlf_subject_body_and_contents() { test_expect_success 'Setup refs with commit and tag messages using CRLF' ' - test_commit inital && + test_commit initial && create_crlf_refs ' diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index 8d50331b8c..a51f881b1c 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -10,7 +10,6 @@ same command line parser, so testing one should be sufficient; pick diff-files as a representative. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index cd1931dd55..4f520d600d 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -5,7 +5,6 @@ test_description='Test rename detection in diff engine.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index cb3307010c..e44648e6f3 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -7,7 +7,6 @@ test_description='Test diff raw-output. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh index ebe091828c..fd4faee5d2 100755 --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -7,7 +7,6 @@ test_description='More rename detection ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index 1d70d4d221..faf3465deb 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -10,7 +10,6 @@ copy of symbolic links, but should not produce rename/copy followed by an edit for them. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh index 5c756dc243..92d1141fbe 100755 --- a/t/t4005-diff-rename-2.sh +++ b/t/t4005-diff-rename-2.sh @@ -6,7 +6,6 @@ test_description='Same rename detection as t4003 but testing diff-raw.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index dbd4c0da21..2299b91fc4 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -7,7 +7,6 @@ test_description='Test mode change diffs. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh sed_script='s/\(:100644 100755\) \('"$OID_REGEX"'\) \2 /\1 X X /' diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh index b86165cbac..e8faf0dd2e 100755 --- a/t/t4007-rename-3.sh +++ b/t/t4007-rename-3.sh @@ -7,7 +7,6 @@ test_description='Rename interaction with pathspec. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh index 562aaf3a2a..c187c52dab 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -21,6 +21,7 @@ With -B, this should be detected as two complete rewrites. Further, with -B and -M together, these should turn into two renames. ' + . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh index 3480781dab..59e71e3acd 100755 --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -7,7 +7,6 @@ test_description='Same rename detection as t4003 but testing diff-raw -z. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 9d9650eba7..c84c3fa05b 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -10,7 +10,6 @@ Prepare: path1/file1 ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index bc8ba88719..ac837b6c9e 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -7,7 +7,6 @@ test_description='Test diff of symlinks. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index c64d9d2f40..d1d30ac2a9 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -6,7 +6,6 @@ test_description='Binary diff and apply ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expect.binary-numstat <<\EOF diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 851cfe4f32..52e3e476ff 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -7,7 +7,6 @@ test_description='Test special whitespace in diff engine. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index 5a8d887683..876271d682 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -6,7 +6,6 @@ test_description='Quoting paths in diff output. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh P0='pathname' diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh index f439f469bd..c2863c99b7 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -5,7 +5,6 @@ test_description='Return value of diffs' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -143,4 +142,49 @@ test_expect_success 'option errors are not confused by --exit-code' ' grep '^usage:' err ' +for option in --exit-code --quiet +do + test_expect_success "git diff $option returns 1 for changed binary file" " + test_when_finished 'rm -f .gitattributes' && + git reset --hard && + echo a binary >.gitattributes && + echo 2 >>a && + test_expect_code 1 git diff $option + " + + test_expect_success "git diff $option returns 1 for copied file" " + git reset --hard && + cp a copy && + git add copy && + test_expect_code 1 git diff $option --cached --find-copies-harder + " + + test_expect_success "git diff $option returns 1 for renamed file" " + git reset --hard && + git mv a renamed && + test_expect_code 1 git diff $option --cached + " +done + +test_expect_success 'setup dirty subrepo' ' + git reset --hard && + test_create_repo subrepo && + test_commit -C subrepo subrepo-file && + test_tick && + git add subrepo && + git commit -m subrepo && + test_commit -C subrepo another-subrepo-file +' + +for option in --exit-code --quiet +do + for submodule_format in diff log short + do + opts="$option --submodule=$submodule_format" && + test_expect_success "git diff $opts returns 1 for dirty subrepo" " + test_expect_code 1 git diff $opts + " + done +done + test_done diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh index d2b3109c2d..4001dacee3 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -2,7 +2,6 @@ test_description='diff whitespace error detection' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 3baa52a9bf..f1efe482a5 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -2,7 +2,6 @@ test_description='external diff interface test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -102,7 +101,7 @@ test_expect_success 'diff attribute' ' test_cmp expect actual ' -test_expect_success !SANITIZE_LEAK 'diff attribute should apply only to diff' ' +test_expect_success 'diff attribute should apply only to diff' ' git log -p -1 HEAD >out && grep "^diff --git a/file b/file" out @@ -129,7 +128,7 @@ test_expect_success 'diff attribute' ' test_cmp expect actual ' -test_expect_success !SANITIZE_LEAK 'diff attribute should apply only to diff' ' +test_expect_success 'diff attribute should apply only to diff' ' git log -p -1 HEAD >out && grep "^diff --git a/file b/file" out diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh index 1219aa226d..9be65fd444 100755 --- a/t/t4021-format-patch-numbered.sh +++ b/t/t4021-format-patch-numbered.sh @@ -5,7 +5,6 @@ test_description='Format-patch numbering options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4024-diff-optimize-common.sh b/t/t4024-diff-optimize-common.sh index e2f0eca4af..b98ac0a0c0 100755 --- a/t/t4024-diff-optimize-common.sh +++ b/t/t4024-diff-optimize-common.sh @@ -2,7 +2,6 @@ test_description='common tail optimization' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh z=zzzzzzzz ;# 8 diff --git a/t/t4025-hunk-header.sh b/t/t4025-hunk-header.sh index 5397cb7d42..c39bb07a41 100755 --- a/t/t4025-hunk-header.sh +++ b/t/t4025-hunk-header.sh @@ -2,7 +2,6 @@ test_description='diff hunk header truncation' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh N='日本語' diff --git a/t/t4026-color.sh b/t/t4026-color.sh index b05f2a9b60..08f6805e1c 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -5,7 +5,6 @@ test_description='Test diff/status color escape codes' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh ESC=$(printf '\033') diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 40164ae07d..295da987cc 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -2,7 +2,6 @@ test_description='difference in submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4028-format-patch-mime-headers.sh b/t/t4028-format-patch-mime-headers.sh index 60cb819c42..a06a747926 100755 --- a/t/t4028-format-patch-mime-headers.sh +++ b/t/t4028-format-patch-mime-headers.sh @@ -2,7 +2,6 @@ test_description='format-patch mime headers and extra headers do not conflict' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create commit with utf-8 body' ' diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh index 5f8ffef74b..32b6e9a4e7 100755 --- a/t/t4029-diff-trailing-space.sh +++ b/t/t4029-diff-trailing-space.sh @@ -4,7 +4,6 @@ # test_description='diff honors config option, diff.suppressBlankEmpty' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat <<\EOF >expected || diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index a39a626664..daebf9796f 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='diff.*.textconv tests' + . ./test-lib.sh find_diff() { diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh index 7db92d0d9f..bada0cbd32 100755 --- a/t/t4032-diff-inter-hunk-context.sh +++ b/t/t4032-diff-inter-hunk-context.sh @@ -2,7 +2,6 @@ test_description='diff hunk fusing' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh f() { diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh index f7be7f5ef0..113304dc59 100755 --- a/t/t4033-diff-patience.sh +++ b/t/t4033-diff-patience.sh @@ -2,7 +2,6 @@ test_description='patience diff algorithm' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-alternative.sh diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 74586f3813..f51d3557f1 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -2,7 +2,6 @@ test_description='word diff colors' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh @@ -70,7 +69,7 @@ test_language_driver () { word_diff --color-words ' test_expect_success "diff driver '$lang' in Islandic" ' - LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \ + test_env LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \ word_diff --color-words ' } diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh index 76f8034c60..0352bf81a9 100755 --- a/t/t4035-diff-quiet.sh +++ b/t/t4035-diff-quiet.sh @@ -2,7 +2,6 @@ test_description='Return value of diffs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4036-format-patch-signer-mime.sh b/t/t4036-format-patch-signer-mime.sh index 48655bcc78..98d9713d8b 100755 --- a/t/t4036-format-patch-signer-mime.sh +++ b/t/t4036-format-patch-signer-mime.sh @@ -2,7 +2,6 @@ test_description='format-patch -s should force MIME encoding as needed' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh index b5f96fe23b..f5ce3b29a2 100755 --- a/t/t4037-diff-r-t-dirs.sh +++ b/t/t4037-diff-r-t-dirs.sh @@ -2,7 +2,6 @@ test_description='diff -r -t shows directory additions and deletions' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4039-diff-assume-unchanged.sh b/t/t4039-diff-assume-unchanged.sh index 78090e6852..0eb0314a8b 100755 --- a/t/t4039-diff-assume-unchanged.sh +++ b/t/t4039-diff-assume-unchanged.sh @@ -2,7 +2,6 @@ test_description='diff with assume-unchanged entries' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # external diff has been tested in t4020-diff-external.sh diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh index eec3d73dc2..1b27a0e381 100755 --- a/t/t4040-whitespace-status.sh +++ b/t/t4040-whitespace-status.sh @@ -2,7 +2,6 @@ test_description='diff --exit-code with whitespace' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 8fc40e75eb..28f9d83d4c 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -12,15 +12,20 @@ This test tries to verify the sanity of the --submodule option of git diff. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -# Tested non-UTF-8 encoding -test_encoding="ISO8859-1" +# Test non-UTF-8 encoding in case iconv is available. +if test_have_prereq ICONV +then + test_encoding="ISO8859-1" + # String "added" in German (translated with Google Translate), encoded in UTF-8, + # used in sample commit log messages in add_file() function below. + added=$(printf "hinzugef\303\274gt") +else + test_encoding="UTF-8" + added="added" +fi -# String "added" in German (translated with Google Translate), encoded in UTF-8, -# used in sample commit log messages in add_file() function below. -added=$(printf "hinzugef\303\274gt") add_file () { ( cd "$1" && diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh index 8ebfa3c1be..ff0e73531b 100755 --- a/t/t4042-diff-textconv-caching.sh +++ b/t/t4042-diff-textconv-caching.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test textconv caching' + . ./test-lib.sh cat >helper <<'EOF' diff --git a/t/t4043-diff-rename-binary.sh b/t/t4043-diff-rename-binary.sh index e486493908..2a2cf91352 100755 --- a/t/t4043-diff-rename-binary.sh +++ b/t/t4043-diff-rename-binary.sh @@ -5,7 +5,6 @@ test_description='Move a binary file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t4044-diff-index-unique-abbrev.sh b/t/t4044-diff-index-unique-abbrev.sh index 9f6043daba..8400bfbd3c 100755 --- a/t/t4044-diff-index-unique-abbrev.sh +++ b/t/t4044-diff-index-unique-abbrev.sh @@ -2,7 +2,6 @@ test_description='test unique sha1 abbreviation on "index from..to" line' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index 9b46c4c1be..2c8493fe66 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -2,7 +2,6 @@ test_description='diff --relative tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4046-diff-unmerged.sh b/t/t4046-diff-unmerged.sh index afda629c98..7c27f05366 100755 --- a/t/t4046-diff-unmerged.sh +++ b/t/t4046-diff-unmerged.sh @@ -2,7 +2,6 @@ test_description='diff with unmerged index entries' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh index 7b73462d53..a7ce8d3161 100755 --- a/t/t4047-diff-dirstat.sh +++ b/t/t4047-diff-dirstat.sh @@ -2,7 +2,6 @@ test_description='diff --dirstat tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # set up two commits where the second commit has these files diff --git a/t/t4049-diff-stat-count.sh b/t/t4049-diff-stat-count.sh index 0a4fc735d4..eceb47c859 100755 --- a/t/t4049-diff-stat-count.sh +++ b/t/t4049-diff-stat-count.sh @@ -3,7 +3,6 @@ test_description='diff --stat-count' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4050-diff-histogram.sh b/t/t4050-diff-histogram.sh index c61b30f96d..fd3e86a74f 100755 --- a/t/t4050-diff-histogram.sh +++ b/t/t4050-diff-histogram.sh @@ -2,7 +2,6 @@ test_description='histogram diff algorithm' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-alternative.sh diff --git a/t/t4051-diff-function-context.sh b/t/t4051-diff-function-context.sh index 725278ad19..4838a1df8b 100755 --- a/t/t4051-diff-function-context.sh +++ b/t/t4051-diff-function-context.sh @@ -2,7 +2,6 @@ test_description='diff function context' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh dir="$TEST_DIRECTORY/t4051" diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 7badd72488..740bb97091 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -8,7 +8,6 @@ test_description='test --stat output of various commands' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 651ec77660..5e5bad61ca 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -2,7 +2,6 @@ test_description='diff --no-index' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh index 05c88f8cdf..1131431fe0 100755 --- a/t/t4054-diff-bogus-tree.sh +++ b/t/t4054-diff-bogus-tree.sh @@ -2,7 +2,6 @@ test_description='test diff with a bogus tree containing the null sha1' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create bogus tree' ' diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh index 3ea9ae99e0..f7ff234cf9 100755 --- a/t/t4055-diff-context.sh +++ b/t/t4055-diff-context.sh @@ -5,7 +5,6 @@ test_description='diff.context configuration' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4057-diff-combined-paths.sh b/t/t4057-diff-combined-paths.sh index 9a7505cbb8..04b8a1542a 100755 --- a/t/t4057-diff-combined-paths.sh +++ b/t/t4057-diff-combined-paths.sh @@ -5,7 +5,6 @@ test_description='combined diff show only paths that are different to all parent GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # verify that diffc.expect matches output of diff --git a/t/t4058-diff-duplicates.sh b/t/t4058-diff-duplicates.sh index 2501c89c1c..2fce4a9897 100755 --- a/t/t4058-diff-duplicates.sh +++ b/t/t4058-diff-duplicates.sh @@ -10,6 +10,7 @@ # that the diff output isn't wildly unreasonable. test_description='test tree diff when trees have duplicate entries' + . ./test-lib.sh # make_tree_entry <mode> <mode> <sha1> @@ -132,22 +133,23 @@ test_expect_success 'create a few commits' ' rm commit_id up final ' -test_expect_failure 'git read-tree does not segfault' ' - test_when_finished rm .git/index.lock && - test_might_fail git read-tree --reset base +test_expect_success 'git read-tree does not segfault' ' + test_must_fail git read-tree --reset base 2>err && + test_grep "error: corrupted cache-tree has entries not present in index" err ' -test_expect_failure 'reset --hard does not segfault' ' - test_when_finished rm .git/index.lock && +test_expect_success 'reset --hard does not segfault' ' git checkout base && - test_might_fail git reset --hard + test_must_fail git reset --hard 2>err && + test_grep "error: corrupted cache-tree has entries not present in index" err ' -test_expect_failure 'git diff HEAD does not segfault' ' +test_expect_success 'git diff HEAD does not segfault' ' git checkout base && GIT_TEST_CHECK_CACHE_TREE=false && git reset --hard && - test_might_fail git diff HEAD + test_must_fail git diff HEAD 2>err && + test_grep "error: corrupted cache-tree has entries not present in index" err ' test_expect_failure 'can switch to another branch when status is empty' ' diff --git a/t/t4059-diff-submodule-not-initialized.sh b/t/t4059-diff-submodule-not-initialized.sh index 668f526303..0fe81056d5 100755 --- a/t/t4059-diff-submodule-not-initialized.sh +++ b/t/t4059-diff-submodule-not-initialized.sh @@ -9,15 +9,20 @@ This test tries to verify that add_submodule_odb works when the submodule was initialized previously but the checkout has since been removed. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -# Tested non-UTF-8 encoding -test_encoding="ISO8859-1" -# String "added" in German (translated with Google Translate), encoded in UTF-8, -# used in sample commit log messages in add_file() function below. -added=$(printf "hinzugef\303\274gt") +# Test non-UTF-8 encoding in case iconv is available. +if test_have_prereq ICONV +then + test_encoding="ISO8859-1" + # String "added" in German (translated with Google Translate), encoded in UTF-8, + # used in sample commit log messages in add_file() function below. + added=$(printf "hinzugef\303\274gt") +else + test_encoding="UTF-8" + added="added" +fi add_file () { ( diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh index 8ce67442d9..76b83101d3 100755 --- a/t/t4060-diff-submodule-option-diff-format.sh +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -10,15 +10,19 @@ test_description='Support for diff format verbose submodule difference in git di This test tries to verify the sanity of --submodule=diff option of git diff. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -# Tested non-UTF-8 encoding -test_encoding="ISO8859-1" - -# String "added" in German (translated with Google Translate), encoded in UTF-8, -# used in sample commit log messages in add_file() function below. -added=$(printf "hinzugef\303\274gt") +# Test non-UTF-8 encoding in case iconv is available. +if test_have_prereq ICONV +then + test_encoding="ISO8859-1" + # String "added" in German (translated with Google Translate), encoded in UTF-8, + # used in sample commit log messages in add_file() function below. + added=$(printf "hinzugef\303\274gt") +else + test_encoding="UTF-8" + added="added" +fi add_file () { ( diff --git a/t/t4061-diff-indent.sh b/t/t4061-diff-indent.sh index 2942e5d9b9..7750b87ca1 100755 --- a/t/t4061-diff-indent.sh +++ b/t/t4061-diff-indent.sh @@ -6,7 +6,6 @@ test_description='Test diff indent heuristic. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4062-diff-pickaxe.sh b/t/t4062-diff-pickaxe.sh index a90b46b678..8ad3d79957 100755 --- a/t/t4062-diff-pickaxe.sh +++ b/t/t4062-diff-pickaxe.sh @@ -5,7 +5,6 @@ test_description='Pickaxe options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4063-diff-blobs.sh b/t/t4063-diff-blobs.sh index 7e6c9d6384..50fdb5ea52 100755 --- a/t/t4063-diff-blobs.sh +++ b/t/t4063-diff-blobs.sh @@ -2,7 +2,6 @@ test_description='test direct comparison of blobs via git-diff' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh run_diff () { diff --git a/t/t4064-diff-oidfind.sh b/t/t4064-diff-oidfind.sh index 6d8c8986fc..e86bba679e 100755 --- a/t/t4064-diff-oidfind.sh +++ b/t/t4064-diff-oidfind.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test finding specific blobs in the revision walking' + . ./test-lib.sh test_expect_success 'setup ' ' diff --git a/t/t4066-diff-emit-delay.sh b/t/t4066-diff-emit-delay.sh index 0ecb391541..a1de63b77f 100755 --- a/t/t4066-diff-emit-delay.sh +++ b/t/t4066-diff-emit-delay.sh @@ -4,7 +4,6 @@ test_description='test combined/stat/moved interaction' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # This test covers a weird 3-way interaction between "--cc -p", which will run diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index 7af3a08862..581250dd2d 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -2,7 +2,6 @@ test_description='behavior of diff when reading objects in a partial clone' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'git show batches blobs' ' diff --git a/t/t4069-remerge-diff.sh b/t/t4069-remerge-diff.sh index 07323ebafe..ca8f999cab 100755 --- a/t/t4069-remerge-diff.sh +++ b/t/t4069-remerge-diff.sh @@ -110,6 +110,41 @@ test_expect_success 'can filter out additional headers with pickaxe' ' test_must_be_empty actual ' +test_expect_success 'remerge-diff also works for git-diff-tree' ' + # With a clean merge + git diff-tree -r -p --remerge-diff --no-commit-id bc_resolution >actual && + test_must_be_empty actual && + + # With both a resolved conflict and an unrelated change + cat <<-EOF >tmp && + diff --git a/numbers b/numbers + remerge CONFLICT (content): Merge conflict in numbers + index a1fb731..6875544 100644 + --- a/numbers + +++ b/numbers + @@ -1,13 +1,9 @@ + 1 + 2 + -<<<<<<< b0ed5cb (change_a) + -three + -======= + -tres + ->>>>>>> 6cd3f82 (change_b) + +drei + 4 + 5 + 6 + 7 + -eight + +acht + 9 + EOF + sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >expect && + git diff-tree -r -p --remerge-diff --no-commit-id ab_resolution >tmp && + sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >actual && + test_cmp expect actual +' + test_expect_success 'setup non-content conflicts' ' git switch --orphan base && diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index d503547732..146e73d8f5 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -7,7 +7,6 @@ test_description='git apply --stat --summary test, with --recount ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/' diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh index b1169193ef..4df74baa24 100755 --- a/t/t4101-apply-nonl.sh +++ b/t/t4101-apply-nonl.sh @@ -7,7 +7,6 @@ test_description='git apply should handle files with incomplete lines. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # setup diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh index d1e06fc1ac..e42a31c917 100755 --- a/t/t4102-apply-rename.sh +++ b/t/t4102-apply-rename.sh @@ -7,7 +7,6 @@ test_description='git apply handling copy/rename patch. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # setup diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index 144619ab87..d370ecfe0d 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -9,7 +9,6 @@ test_description='git apply handling binary patches GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh index dc501aac38..71ef4132d1 100755 --- a/t/t4104-apply-boundary.sh +++ b/t/t4104-apply-boundary.sh @@ -5,7 +5,6 @@ test_description='git apply boundary tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh L="c d e f g h i j k l m n o p q r s t u v w x" diff --git a/t/t4105-apply-fuzz.sh b/t/t4105-apply-fuzz.sh index ed814a839e..b59785166d 100755 --- a/t/t4105-apply-fuzz.sh +++ b/t/t4105-apply-fuzz.sh @@ -3,7 +3,6 @@ test_description='apply with fuzz and offset' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh dotest () { diff --git a/t/t4106-apply-stdin.sh b/t/t4106-apply-stdin.sh index 5c150f3b0b..aa2fff7afa 100755 --- a/t/t4106-apply-stdin.sh +++ b/t/t4106-apply-stdin.sh @@ -3,7 +3,6 @@ test_description='git apply --numstat - <patch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh index ac72eeaf27..94ba6dd4e0 100755 --- a/t/t4107-apply-ignore-whitespace.sh +++ b/t/t4107-apply-ignore-whitespace.sh @@ -3,9 +3,8 @@ # Copyright (c) 2009 Giuseppe Bilotta # -test_description='git-apply --ignore-whitespace. +test_description='git-apply --ignore-whitespace.' -' . ./test-lib.sh # This primes main.c file that indents without using HT at all. diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh index c558282bc0..f30e85659d 100755 --- a/t/t4108-apply-threeway.sh +++ b/t/t4108-apply-threeway.sh @@ -81,6 +81,46 @@ test_expect_success 'apply with --3way with merge.conflictStyle = diff3' ' test_apply_with_3way ' +test_apply_with_3way_favoritism () { + apply_arg=$1 + merge_arg=$2 + + # Merging side should be similar to applying this patch + git diff ...side >P.diff && + + # The corresponding conflicted merge + git reset --hard && + git checkout main^0 && + git merge --no-commit $merge_arg side && + git ls-files -s >expect.ls && + print_sanitized_conflicted_diff >expect.diff && + + # should apply successfully + git reset --hard && + git checkout main^0 && + git apply --index --3way $apply_arg P.diff && + git ls-files -s >actual.ls && + print_sanitized_conflicted_diff >actual.diff && + + # The result should resemble the corresponding merge + test_cmp expect.ls actual.ls && + test_cmp expect.diff actual.diff +} + +test_expect_success 'apply with --3way --ours' ' + test_apply_with_3way_favoritism --ours -Xours +' + +test_expect_success 'apply with --3way --theirs' ' + test_apply_with_3way_favoritism --theirs -Xtheirs +' + +test_expect_success 'apply with --3way --union' ' + echo "* merge=union" >.gitattributes && + test_apply_with_3way_favoritism --union && + rm .gitattributes +' + test_expect_success 'apply with --3way with rerere enabled' ' test_config rerere.enabled true && diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh index 4dc6d8e7d3..ac523a5d56 100755 --- a/t/t4109-apply-multifrag.sh +++ b/t/t4109-apply-multifrag.sh @@ -7,7 +7,6 @@ test_description='git apply test patches with multiple fragments.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cp "$TEST_DIRECTORY/t4109/patch1.patch" . diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh index 266302a182..cc17ff2ab9 100755 --- a/t/t4110-apply-scan.sh +++ b/t/t4110-apply-scan.sh @@ -8,7 +8,6 @@ test_description='git apply test for patches which require scanning forwards and ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'git apply scan' ' diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh index e9a87d761d..1618a6dbc7 100755 --- a/t/t4111-apply-subdir.sh +++ b/t/t4111-apply-subdir.sh @@ -2,7 +2,6 @@ test_description='patching from inconvenient places' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index d53aa4222e..bb5d529bec 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -8,7 +8,6 @@ test_description='git apply should not get confused with rename/copy. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # setup diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh index 2c65c6a169..66fa51591e 100755 --- a/t/t4113-apply-ending.sh +++ b/t/t4113-apply-ending.sh @@ -6,7 +6,6 @@ test_description='git apply trying to add an ending line. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # setup diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index 8ff3640766..da3e64f811 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -7,7 +7,6 @@ test_description='git apply should not get confused with type changes. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup repository and commits' ' diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index cbef0a593f..769b0e4f9d 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -7,7 +7,6 @@ test_description='git apply symlinks and partial files ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh index a9f4ddda6c..0784ba033a 100755 --- a/t/t4116-apply-reverse.sh +++ b/t/t4116-apply-reverse.sh @@ -8,7 +8,6 @@ test_description='git apply in reverse ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh index 4d15ccd28e..c86d05a96f 100755 --- a/t/t4117-apply-reject.sh +++ b/t/t4117-apply-reject.sh @@ -7,7 +7,6 @@ test_description='git apply with rejects ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 69c9c48e72..c1dcbd7d35 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -8,7 +8,6 @@ test_description='git apply with new style GNU diff with empty context ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index 208c961d37..f3b43e2216 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -8,7 +8,6 @@ test_description='git apply --whitespace=strip and configuration file. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh index f788428540..697e86c0ff 100755 --- a/t/t4120-apply-popt.sh +++ b/t/t4120-apply-popt.sh @@ -5,7 +5,6 @@ test_description='git apply -p handling.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4121-apply-diffs.sh b/t/t4121-apply-diffs.sh index a80cec9d11..b45454aaf4 100755 --- a/t/t4121-apply-diffs.sh +++ b/t/t4121-apply-diffs.sh @@ -4,7 +4,6 @@ test_description='git apply for contextually independent diffs' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh echo '1 diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 2089d84f64..3340ab4370 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -4,7 +4,6 @@ test_description='apply to deeper directory without getting fooled with symlink' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4123-apply-shrink.sh b/t/t4123-apply-shrink.sh index 3601c0c5dc..3ef84619f5 100755 --- a/t/t4123-apply-shrink.sh +++ b/t/t4123-apply-shrink.sh @@ -2,7 +2,6 @@ test_description='apply a patch that is larger than the preimage' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >F <<\EOF diff --git a/t/t4126-apply-empty.sh b/t/t4126-apply-empty.sh index 56210b5609..eff783f8d6 100755 --- a/t/t4126-apply-empty.sh +++ b/t/t4126-apply-empty.sh @@ -2,7 +2,6 @@ test_description='apply empty' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh index aa5cfae2b6..bd516c4aad 100755 --- a/t/t4127-apply-same-fn.sh +++ b/t/t4127-apply-same-fn.sh @@ -3,7 +3,6 @@ test_description='apply same filename' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh modify () { diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh index ed94c90204..f6db5a79dd 100755 --- a/t/t4128-apply-root.sh +++ b/t/t4128-apply-root.sh @@ -2,7 +2,6 @@ test_description='apply same filename' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh index 4eb8444029..2149ad5da4 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -3,7 +3,6 @@ test_description='applying patch with mode bits' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -130,4 +129,66 @@ test_expect_success 'git apply respects core.fileMode' ' test_grep ! "has type 100644, expected 100755" err ' +test_expect_success POSIXPERM 'patch mode for new file is canonicalized' ' + cat >patch <<-\EOF && + diff --git a/non-canon b/non-canon + new file mode 100660 + --- /dev/null + +++ b/non-canon + +content + EOF + test_when_finished "git reset --hard" && + ( + umask 0 && + git apply --index patch 2>err + ) && + test_must_be_empty err && + git ls-files -s -- non-canon >staged && + test_grep "^100644" staged && + ls -l non-canon >worktree && + test_grep "^-rw-rw-rw" worktree +' + +test_expect_success POSIXPERM 'patch mode for deleted file is canonicalized' ' + test_when_finished "git reset --hard" && + echo content >non-canon && + chmod 666 non-canon && + git add non-canon && + + cat >patch <<-\EOF && + diff --git a/non-canon b/non-canon + deleted file mode 100660 + --- a/non-canon + +++ /dev/null + @@ -1 +0,0 @@ + -content + EOF + git apply --index patch 2>err && + test_must_be_empty err && + git ls-files -- non-canon >staged && + test_must_be_empty staged && + test_path_is_missing non-canon +' + +test_expect_success POSIXPERM 'patch mode for mode change is canonicalized' ' + test_when_finished "git reset --hard" && + echo content >non-canon && + git add non-canon && + + cat >patch <<-\EOF && + diff --git a/non-canon b/non-canon + old mode 100660 + new mode 100770 + EOF + ( + umask 0 && + git apply --index patch 2>err + ) && + test_must_be_empty err && + git ls-files -s -- non-canon >staged && + test_grep "^100755" staged && + ls -l non-canon >worktree && + test_grep "^-rwxrwxrwx" worktree +' + test_done diff --git a/t/t4130-apply-criss-cross-rename.sh b/t/t4130-apply-criss-cross-rename.sh index f3ea632742..211ef1c7e7 100755 --- a/t/t4130-apply-criss-cross-rename.sh +++ b/t/t4130-apply-criss-cross-rename.sh @@ -2,7 +2,6 @@ test_description='git apply handling criss-cross rename patch.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh create_file() { diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh index 40c92115a6..b1361ce546 100755 --- a/t/t4131-apply-fake-ancestor.sh +++ b/t/t4131-apply-fake-ancestor.sh @@ -5,7 +5,6 @@ test_description='git apply --build-fake-ancestor handling.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4132-apply-removal.sh b/t/t4132-apply-removal.sh index c1e3049c04..ab1628d27d 100755 --- a/t/t4132-apply-removal.sh +++ b/t/t4132-apply-removal.sh @@ -5,7 +5,6 @@ test_description='git-apply notices removal patches generated by GNU diff' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4133-apply-filenames.sh b/t/t4133-apply-filenames.sh index c21ddb2946..3cab1038cf 100755 --- a/t/t4133-apply-filenames.sh +++ b/t/t4133-apply-filenames.sh @@ -6,7 +6,6 @@ test_description='git apply filename consistency check' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4134-apply-submodule.sh b/t/t4134-apply-submodule.sh index aceb4c42b0..8cea75cf7b 100755 --- a/t/t4134-apply-submodule.sh +++ b/t/t4134-apply-submodule.sh @@ -6,7 +6,6 @@ test_description='git apply submodule tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4135-apply-weird-filenames.sh b/t/t4135-apply-weird-filenames.sh index d3502c6fdd..6bc3fb97a7 100755 --- a/t/t4135-apply-weird-filenames.sh +++ b/t/t4135-apply-weird-filenames.sh @@ -2,7 +2,6 @@ test_description='git apply with weird postimage filenames' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4136-apply-check.sh b/t/t4136-apply-check.sh index dfec1c5f0f..82f2f2e475 100755 --- a/t/t4136-apply-check.sh +++ b/t/t4136-apply-check.sh @@ -3,7 +3,6 @@ test_description='git apply should exit non-zero with unrecognized input.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4137-apply-submodule.sh b/t/t4137-apply-submodule.sh index ebd0d4ad17..07d5262537 100755 --- a/t/t4137-apply-submodule.sh +++ b/t/t4137-apply-submodule.sh @@ -2,7 +2,6 @@ test_description='git apply handling submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t4139-apply-escape.sh b/t/t4139-apply-escape.sh index e5c7439df1..e07fb9ef08 100755 --- a/t/t4139-apply-escape.sh +++ b/t/t4139-apply-escape.sh @@ -2,7 +2,6 @@ test_description='paths written by git-apply cannot escape the working tree' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # tests will try to write to ../foo, and we do not diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh index b375aca0d7..c614eaf04c 100755 --- a/t/t4140-apply-ita.sh +++ b/t/t4140-apply-ita.sh @@ -2,7 +2,6 @@ test_description='git apply of i-t-a file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4141-apply-too-large.sh b/t/t4141-apply-too-large.sh index 20cc1209f6..eac6f7e151 100755 --- a/t/t4141-apply-too-large.sh +++ b/t/t4141-apply-too-large.sh @@ -2,7 +2,6 @@ test_description='git apply with too-large patch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success EXPENSIVE 'git apply rejects patches that are too large' ' diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index 1825a89d6a..edb38da701 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -2,7 +2,6 @@ test_description='am --abort' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh index 9f2edba1f8..768495b131 100755 --- a/t/t4152-am-subjects.sh +++ b/t/t4152-am-subjects.sh @@ -2,7 +2,6 @@ test_description='test subject preservation with format-patch | am' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh make_patches() { diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh index dd6ad8f7a8..9bec989a0e 100755 --- a/t/t4153-am-resume-override-opts.sh +++ b/t/t4153-am-resume-override-opts.sh @@ -2,7 +2,6 @@ test_description='git-am command-line options override saved options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh format_patch () { diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 213b36fb96..b0a3e84984 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -25,7 +25,6 @@ test_description='git rerere GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index c20c885724..5f23fc147b 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -9,7 +9,6 @@ test_description='git shortlog GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -105,7 +104,7 @@ test_expect_success 'output from user-defined format is re-wrapped' ' test_cmp expect log.predictable ' -test_expect_success !MINGW 'shortlog wrapping' ' +test_expect_success !MINGW,ICONV 'shortlog wrapping' ' cat >expect <<\EOF && A U Thor (5): Test @@ -126,13 +125,13 @@ EOF test_cmp expect out ' -test_expect_success !MINGW 'shortlog from non-git directory' ' +test_expect_success !MINGW,ICONV 'shortlog from non-git directory' ' git log --no-expand-tabs HEAD >log && GIT_DIR=non-existing git shortlog -w <log >out && test_cmp expect out ' -test_expect_success !MINGW 'shortlog can read --format=raw output' ' +test_expect_success !MINGW,ICONV 'shortlog can read --format=raw output' ' git log --format=raw HEAD >log && GIT_DIR=non-existing git shortlog -w <log >out && test_cmp expect out @@ -143,6 +142,10 @@ test_expect_success 'shortlog from non-git directory refuses extra arguments' ' test_grep "too many arguments" out ' +test_expect_success 'shortlog --author from non-git directory does not segfault' ' + nongit git shortlog --author=author </dev/null +' + test_expect_success 'shortlog should add newline when input line matches wraplen' ' cat >expect <<\EOF && A U Thor (2): @@ -182,7 +185,7 @@ $DSCHO (2): EOF -test_expect_success !MINGW 'shortlog encoding' ' +test_expect_success !MINGW,ICONV 'shortlog encoding' ' git reset --hard "$commit" && git config --unset i18n.commitencoding && echo 2 > a1 && diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 8a88dd7900..2421491931 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -71,12 +71,46 @@ test_expect_success 'check-mailmap --stdin arguments: mapping' ' test_cmp expect actual ' -test_expect_success 'check-mailmap bogus contact' ' - test_must_fail git check-mailmap bogus +test_expect_success 'check-mailmap simple address: mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + New Name <$GIT_AUTHOR_EMAIL> + EOF + cat .mailmap >expect && + git check-mailmap "$GIT_AUTHOR_EMAIL" >actual && + test_cmp expect actual +' + +test_expect_success 'check-mailmap --stdin simple address: mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + New Name <$GIT_AUTHOR_EMAIL> + EOF + cat >stdin <<-EOF && + $GIT_AUTHOR_EMAIL + EOF + cat .mailmap >expect && + git check-mailmap --stdin <stdin >actual && + test_cmp expect actual +' + +test_expect_success 'check-mailmap simple address: no mapping' ' + cat >expect <<-EOF && + <bugs@company.xx> + EOF + git check-mailmap "bugs@company.xx" >actual && + test_cmp expect actual ' -test_expect_success 'check-mailmap bogus contact --stdin' ' - test_must_fail git check-mailmap --stdin bogus </dev/null +test_expect_success 'check-mailmap --stdin simple address: no mapping' ' + cat >expect <<-EOF && + <bugs@company.xx> + EOF + cat >stdin <<-EOF && + bugs@company.xx + EOF + git check-mailmap --stdin <stdin >actual && + test_cmp expect actual ' test_expect_success 'No mailmap' ' diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index 158b49d4b6..f81e42a84d 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -5,6 +5,7 @@ # test_description='Test pretty formats' + . ./test-lib.sh # Tested non-UTF-8 encoding @@ -112,19 +113,19 @@ test_expect_success 'alias loop' ' test_must_fail git log --pretty=test-foo ' -test_expect_success 'NUL separation' ' +test_expect_success ICONV 'NUL separation' ' printf "add bar\0$(commit_msg)" >expected && git log -z --pretty="format:%s" >actual && test_cmp expected actual ' -test_expect_success 'NUL termination' ' +test_expect_success ICONV 'NUL termination' ' printf "add bar\0$(commit_msg)\0" >expected && git log -z --pretty="tformat:%s" >actual && test_cmp expected actual ' -test_expect_success 'NUL separation with --stat' ' +test_expect_success ICONV 'NUL separation with --stat' ' stat0_part=$(git diff --stat HEAD^ HEAD) && stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) && printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n" >expected && @@ -135,7 +136,7 @@ test_expect_success 'NUL separation with --stat' ' test_expect_failure 'NUL termination with --stat' ' stat0_part=$(git diff --stat HEAD^ HEAD) && stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) && - printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n0" >expected && + printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n\0" >expected && git log -z --stat --pretty="tformat:%s" >actual && test_cmp expected actual ' @@ -179,7 +180,7 @@ test_expect_success 'setup more commits' ' head4=$(git rev-parse --verify --short HEAD~3) ' -test_expect_success 'left alignment formatting' ' +test_expect_success ICONV 'left alignment formatting' ' git log --pretty="tformat:%<(40)%s" >actual && qz_to_tab_space <<-EOF >expected && message two Z @@ -190,7 +191,7 @@ test_expect_success 'left alignment formatting' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && message two Z @@ -201,7 +202,7 @@ test_expect_success 'left alignment formatting. i18n.logOutputEncoding' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting at the nth column' ' +test_expect_success ICONV 'left alignment formatting at the nth column' ' git log --pretty="tformat:%h %<|(40)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two Z @@ -212,7 +213,7 @@ test_expect_success 'left alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting at the nth column' ' +test_expect_success ICONV 'left alignment formatting at the nth column' ' COLUMNS=50 git log --pretty="tformat:%h %<|(-10)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two Z @@ -223,7 +224,7 @@ test_expect_success 'left alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting at the nth column. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %<|(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && $head1 message two Z @@ -234,7 +235,7 @@ test_expect_success 'left alignment formatting at the nth column. i18n.logOutput test_cmp expected actual ' -test_expect_success 'left alignment formatting with no padding' ' +test_expect_success ICONV 'left alignment formatting with no padding' ' git log --pretty="tformat:%<(1)%s" >actual && cat <<-EOF >expected && message two @@ -256,7 +257,7 @@ test_expect_success 'left alignment formatting with no padding. i18n.logOutputEn test_cmp expected actual ' -test_expect_success 'left alignment formatting with trunc' ' +test_expect_success ICONV 'left alignment formatting with trunc' ' git log --pretty="tformat:%<(10,trunc)%s" >actual && qz_to_tab_space <<-\EOF >expected && message .. @@ -267,7 +268,7 @@ test_expect_success 'left alignment formatting with trunc' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting with trunc. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left alignment formatting with trunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s" >actual && qz_to_tab_space <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && message .. @@ -278,7 +279,7 @@ test_expect_success 'left alignment formatting with trunc. i18n.logOutputEncodin test_cmp expected actual ' -test_expect_success 'left alignment formatting with ltrunc' ' +test_expect_success ICONV 'left alignment formatting with ltrunc' ' git log --pretty="tformat:%<(10,ltrunc)%s" >actual && qz_to_tab_space <<-EOF >expected && ..sage two @@ -289,7 +290,7 @@ test_expect_success 'left alignment formatting with ltrunc' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting with ltrunc. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left alignment formatting with ltrunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,ltrunc)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && ..sage two @@ -300,7 +301,7 @@ test_expect_success 'left alignment formatting with ltrunc. i18n.logOutputEncodi test_cmp expected actual ' -test_expect_success 'left alignment formatting with mtrunc' ' +test_expect_success ICONV 'left alignment formatting with mtrunc' ' git log --pretty="tformat:%<(10,mtrunc)%s" >actual && qz_to_tab_space <<-\EOF >expected && mess.. two @@ -311,7 +312,7 @@ test_expect_success 'left alignment formatting with mtrunc' ' test_cmp expected actual ' -test_expect_success 'left alignment formatting with mtrunc. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left alignment formatting with mtrunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,mtrunc)%s" >actual && qz_to_tab_space <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && mess.. two @@ -322,7 +323,7 @@ test_expect_success 'left alignment formatting with mtrunc. i18n.logOutputEncodi test_cmp expected actual ' -test_expect_success 'right alignment formatting' ' +test_expect_success ICONV 'right alignment formatting' ' git log --pretty="tformat:%>(40)%s" >actual && qz_to_tab_space <<-EOF >expected && Z message two @@ -333,7 +334,7 @@ test_expect_success 'right alignment formatting' ' test_cmp expected actual ' -test_expect_success 'right alignment formatting. i18n.logOutputEncoding' ' +test_expect_success ICONV 'right alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && Z message two @@ -344,7 +345,7 @@ test_expect_success 'right alignment formatting. i18n.logOutputEncoding' ' test_cmp expected actual ' -test_expect_success 'right alignment formatting at the nth column' ' +test_expect_success ICONV 'right alignment formatting at the nth column' ' git log --pretty="tformat:%h %>|(40)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two @@ -355,7 +356,7 @@ test_expect_success 'right alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'right alignment formatting at the nth column' ' +test_expect_success ICONV 'right alignment formatting at the nth column' ' COLUMNS=50 git log --pretty="tformat:%h %>|(-10)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two @@ -366,7 +367,7 @@ test_expect_success 'right alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'right alignment formatting at the nth column. i18n.logOutputEncoding' ' +test_expect_success ICONV 'right alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %>|(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && $head1 message two @@ -379,7 +380,7 @@ test_expect_success 'right alignment formatting at the nth column. i18n.logOutpu # Note: Space between 'message' and 'two' should be in the same column # as in previous test. -test_expect_success 'right alignment formatting at the nth column with --graph. i18n.logOutputEncoding' ' +test_expect_success ICONV 'right alignment formatting at the nth column with --graph. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --graph --pretty="tformat:%h %>|(40)%s" >actual && iconv -f utf-8 -t $test_encoding >expected <<-EOF && * $head1 message two @@ -390,7 +391,7 @@ test_expect_success 'right alignment formatting at the nth column with --graph. test_cmp expected actual ' -test_expect_success 'right alignment formatting with no padding' ' +test_expect_success ICONV 'right alignment formatting with no padding' ' git log --pretty="tformat:%>(1)%s" >actual && cat <<-EOF >expected && message two @@ -401,7 +402,7 @@ test_expect_success 'right alignment formatting with no padding' ' test_cmp expected actual ' -test_expect_success 'right alignment formatting with no padding and with --graph' ' +test_expect_success ICONV 'right alignment formatting with no padding and with --graph' ' git log --graph --pretty="tformat:%>(1)%s" >actual && cat <<-EOF >expected && * message two @@ -412,7 +413,7 @@ test_expect_success 'right alignment formatting with no padding and with --graph test_cmp expected actual ' -test_expect_success 'right alignment formatting with no padding. i18n.logOutputEncoding' ' +test_expect_success ICONV 'right alignment formatting with no padding. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(1)%s" >actual && cat <<-EOF | iconv -f utf-8 -t $test_encoding >expected && message two @@ -423,7 +424,7 @@ test_expect_success 'right alignment formatting with no padding. i18n.logOutputE test_cmp expected actual ' -test_expect_success 'center alignment formatting' ' +test_expect_success ICONV 'center alignment formatting' ' git log --pretty="tformat:%><(40)%s" >actual && qz_to_tab_space <<-EOF >expected && Z message two Z @@ -434,7 +435,7 @@ test_expect_success 'center alignment formatting' ' test_cmp expected actual ' -test_expect_success 'center alignment formatting. i18n.logOutputEncoding' ' +test_expect_success ICONV 'center alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && Z message two Z @@ -444,7 +445,7 @@ test_expect_success 'center alignment formatting. i18n.logOutputEncoding' ' EOF test_cmp expected actual ' -test_expect_success 'center alignment formatting at the nth column' ' +test_expect_success ICONV 'center alignment formatting at the nth column' ' git log --pretty="tformat:%h %><|(40)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two Z @@ -455,7 +456,7 @@ test_expect_success 'center alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'center alignment formatting at the nth column' ' +test_expect_success ICONV 'center alignment formatting at the nth column' ' COLUMNS=70 git log --pretty="tformat:%h %><|(-30)%s" >actual && qz_to_tab_space <<-EOF >expected && $head1 message two Z @@ -466,7 +467,7 @@ test_expect_success 'center alignment formatting at the nth column' ' test_cmp expected actual ' -test_expect_success 'center alignment formatting at the nth column. i18n.logOutputEncoding' ' +test_expect_success ICONV 'center alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %><|(40)%s" >actual && qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && $head1 message two Z @@ -477,7 +478,7 @@ test_expect_success 'center alignment formatting at the nth column. i18n.logOutp test_cmp expected actual ' -test_expect_success 'center alignment formatting with no padding' ' +test_expect_success ICONV 'center alignment formatting with no padding' ' git log --pretty="tformat:%><(1)%s" >actual && cat <<-EOF >expected && message two @@ -491,7 +492,7 @@ test_expect_success 'center alignment formatting with no padding' ' # save HEAD's SHA-1 digest (with no abbreviations) to use it below # as far as the next test amends HEAD old_head1=$(git rev-parse --verify HEAD~0) -test_expect_success 'center alignment formatting with no padding. i18n.logOutputEncoding' ' +test_expect_success ICONV 'center alignment formatting with no padding. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(1)%s" >actual && cat <<-EOF | iconv -f utf-8 -t $test_encoding >expected && message two @@ -502,7 +503,7 @@ test_expect_success 'center alignment formatting with no padding. i18n.logOutput test_cmp expected actual ' -test_expect_success 'left/right alignment formatting with stealing' ' +test_expect_success ICONV 'left/right alignment formatting with stealing' ' git commit --amend -m short --author "long long long <long@me.com>" && git log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual && cat <<-\EOF >expected && @@ -513,7 +514,7 @@ test_expect_success 'left/right alignment formatting with stealing' ' EOF test_cmp expected actual ' -test_expect_success 'left/right alignment formatting with stealing. i18n.logOutputEncoding' ' +test_expect_success ICONV 'left/right alignment formatting with stealing. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual && cat <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && short long long long @@ -562,22 +563,38 @@ test_expect_success 'log decoration properly follows tag chain' ' git tag -d tag1 && git commit --amend -m shorter && git log --no-walk --tags --pretty="%H %d" --decorate=full >actual && - cat <<-EOF >expected && - $head2 (tag: refs/tags/message-one) - $old_head1 (tag: refs/tags/message-two) - $head1 (tag: refs/tags/tag2) - EOF + if test_have_prereq ICONV + then + cat <<-EOF >expected + $head2 (tag: refs/tags/message-one) + $old_head1 (tag: refs/tags/message-two) + $head1 (tag: refs/tags/tag2) + EOF + else + cat <<-EOF >expected + $head2 (tag: refs/tags/message-one) + $old_head1 (tag: refs/tags/tag2, tag: refs/tags/message-two) + EOF + fi && sort -k3 actual >actual1 && test_cmp expected actual1 ' test_expect_success 'clean log decoration' ' git log --no-walk --tags --pretty="%H %D" --decorate=full >actual && - cat >expected <<-EOF && - $head2 tag: refs/tags/message-one - $old_head1 tag: refs/tags/message-two - $head1 tag: refs/tags/tag2 - EOF + if test_have_prereq ICONV + then + cat <<-EOF >expected + $head2 tag: refs/tags/message-one + $old_head1 tag: refs/tags/message-two + $head1 tag: refs/tags/tag2 + EOF + else + cat <<-EOF >expected + $head2 tag: refs/tags/message-one + $old_head1 tag: refs/tags/tag2, tag: refs/tags/message-two + EOF + fi && sort -k3 actual >actual1 && test_cmp expected actual1 ' diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh index 9167b0351f..bcab71c8e8 100755 --- a/t/t4206-log-follow-harder-copies.sh +++ b/t/t4206-log-follow-harder-copies.sh @@ -7,7 +7,6 @@ test_description='Test --follow should always find copies hard in git log. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index 73ea9e5155..0614511656 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -8,7 +8,6 @@ test_description='test "git log --decorate" colors' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index 2a46eb6bed..806b2809d4 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -5,7 +5,6 @@ test_description='magic pathspec tests using git-log' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh index 64e1623733..a675ace081 100755 --- a/t/t4209-log-pickaxe.sh +++ b/t/t4209-log-pickaxe.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='log --grep/--author/--regexp-ignore-case/-S/-G' + . ./test-lib.sh test_log () { diff --git a/t/t4210-log-i18n.sh b/t/t4210-log-i18n.sh index 7120030b5c..26dda0db38 100755 --- a/t/t4210-log-i18n.sh +++ b/t/t4210-log-i18n.sh @@ -2,9 +2,14 @@ test_description='test log with i18n features' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh +if ! test_have_prereq ICONV +then + skip_all='skipping log i18n tests; iconv not available' + test_done +fi + # two forms of é utf8_e=$(printf '\303\251') latin1_e=$(printf '\351') diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 02d76dca28..950451cf6a 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -337,4 +337,32 @@ test_expect_success 'zero-width regex .* matches any function name' ' test_cmp expect actual ' +test_expect_success 'show line-log with graph' ' + qz_to_tab_space >expect <<-EOF && + * $head_oid Modify func2() in file.c + |Z + | diff --git a/file.c b/file.c + | --- a/file.c + | +++ b/file.c + | @@ -6,4 +6,4 @@ + | int func2() + | { + | - return F2; + | + return F2 + 2; + | } + * $root_oid Add func1() and func2() in file.c + ZZ + diff --git a/file.c b/file.c + --- /dev/null + +++ b/file.c + @@ -0,0 +6,4 @@ + +int func2() + +{ + + return F2; + +} + EOF + git log --graph --oneline -L:func2:file.c >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh index e6b59123a3..64d818bc70 100755 --- a/t/t4212-log-corrupt.sh +++ b/t/t4212-log-corrupt.sh @@ -2,7 +2,6 @@ test_description='git log with invalid commit headers' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh index 590fce95e9..53a4af3244 100755 --- a/t/t4213-log-tabexpand.sh +++ b/t/t4213-log-tabexpand.sh @@ -2,7 +2,6 @@ test_description='log/show --expand-tabs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh HT=" " diff --git a/t/t4214-log-graph-octopus.sh b/t/t4214-log-graph-octopus.sh index 7905597869..f70c46bbbf 100755 --- a/t/t4214-log-graph-octopus.sh +++ b/t/t4214-log-graph-octopus.sh @@ -5,7 +5,6 @@ test_description='git log --graph of skewed left octopus merge.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-log-graph.sh diff --git a/t/t4215-log-skewed-merges.sh b/t/t4215-log-skewed-merges.sh index b877ac7235..28d0779a8c 100755 --- a/t/t4215-log-skewed-merges.sh +++ b/t/t4215-log-skewed-merges.sh @@ -2,7 +2,6 @@ test_description='git log --graph of skewed merges' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-log-graph.sh diff --git a/t/t4217-log-limit.sh b/t/t4217-log-limit.sh index 613f0710e9..6e01e2629c 100755 --- a/t/t4217-log-limit.sh +++ b/t/t4217-log-limit.sh @@ -2,7 +2,6 @@ test_description='git log with filter options limiting the output' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup test' ' diff --git a/t/t4252-am-options.sh b/t/t4252-am-options.sh index 5b680dc755..bda8822b3d 100755 --- a/t/t4252-am-options.sh +++ b/t/t4252-am-options.sh @@ -2,7 +2,6 @@ test_description='git am with options and not losing them' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh tm="$TEST_DIRECTORY/t4252" diff --git a/t/t4253-am-keep-cr-dos.sh b/t/t4253-am-keep-cr-dos.sh index 2bcdd9f34f..0ee69d2a0c 100755 --- a/t/t4253-am-keep-cr-dos.sh +++ b/t/t4253-am-keep-cr-dos.sh @@ -9,7 +9,6 @@ test_description='git-am mbox with dos line ending. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Three patches which will be added as files with dos line ending. diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh index 661feb6070..ae0a56cf5e 100755 --- a/t/t4254-am-corrupt.sh +++ b/t/t4254-am-corrupt.sh @@ -2,9 +2,14 @@ test_description='git am with corrupt input' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +if ! test_have_prereq ICONV +then + skip_all='skipping am encoding corruption tests; iconv not available' + test_done +fi + make_mbox_with_nul () { space=' ' q_nul_in_subject= diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh index 04f3ccfc41..a7ba08f728 100755 --- a/t/t4255-am-submodule.sh +++ b/t/t4255-am-submodule.sh @@ -2,7 +2,6 @@ test_description='git am handling submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh index 92d8c8b651..ac9db285f3 100755 --- a/t/t4256-am-format-flowed.sh +++ b/t/t4256-am-format-flowed.sh @@ -2,7 +2,6 @@ test_description='test format=flowed support of git am' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh index f26d7fd2db..30a565cbea 100755 --- a/t/t4257-am-interactive.sh +++ b/t/t4257-am-interactive.sh @@ -2,7 +2,6 @@ test_description='am --interactive tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up patches to apply' ' diff --git a/t/t4258-am-quoted-cr.sh b/t/t4258-am-quoted-cr.sh index 3573c9147f..201915b45a 100755 --- a/t/t4258-am-quoted-cr.sh +++ b/t/t4258-am-quoted-cr.sh @@ -2,7 +2,6 @@ test_description='test am --quoted-cr=<action>' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh DATA="$TEST_DIRECTORY/t4258" diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh index 9c197260d5..27fbe193bc 100755 --- a/t/t4300-merge-tree.sh +++ b/t/t4300-merge-tree.sh @@ -5,7 +5,6 @@ test_description='git merge-tree' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 72b8d0ff02..5465054f17 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -136,6 +136,8 @@ test_expect_success 'end-of-options is correctly eaten' ' test_expect_success 'populate workdir' ' mkdir a && + echo "a files_named_a" >.gitattributes && + git add .gitattributes && echo simple textfile >a/a && ten=0123456789 && hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" && @@ -449,6 +451,16 @@ test_expect_success 'allow pathspecs that resolve to the current directory' ' test_cmp expect actual ' +test_expect_success 'attr pathspec in bare repo' ' + test_expect_code 0 git --git-dir=bare.git archive -v HEAD \ + ":(attr:files_named_a)" >/dev/null 2>actual && + cat >expect <<-\EOF && + a/ + a/a + EOF + test_cmp expect actual +' + # Pull the size and date of each entry in a tarfile using the system tar. # # We'll pull out only the year from the date; that avoids any question of diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 7310774af5..e745076441 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -3,7 +3,6 @@ test_description='git archive attribute tests' TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh SUBSTFORMAT='%H (%h)%n' diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh index 78ab75f1bc..97c93f6c44 100755 --- a/t/t5002-archive-attr-pattern.sh +++ b/t/t5002-archive-attr-pattern.sh @@ -2,7 +2,6 @@ test_description='git archive attribute pattern tests' -TEST_PASSES_SANITIZE_LEAK=true TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 9f2c6da80e..50344e17ca 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -2,7 +2,6 @@ test_description='test corner cases of git-archive' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # the 10knuls.tar file is used to test for an empty git generated tar diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index c8d0655454..e57e1ae739 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -27,7 +27,12 @@ check_mailinfo () { for mail in 00* do - test_expect_success "mailinfo $mail" ' + case "$mail" in + 0004) + prereq=ICONV;; + esac + + test_expect_success $prereq "mailinfo $mail" ' check_mailinfo "$mail" "" && if test -f "$DATA/msg$mail--scissors" then @@ -55,7 +60,12 @@ test_expect_success 'split box with rfc2047 samples' \ for mail in rfc2047/00* do - test_expect_success "mailinfo $mail" ' + case "$mail" in + rfc2047/0001) + prereq=ICONV;; + esac + + test_expect_success $prereq "mailinfo $mail" ' git mailinfo -u "$mail-msg" "$mail-patch" <"$mail" >"$mail-info" && echo msg && test_cmp "$DATA/empty" "$mail-msg" && diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index 86bee33160..cb67bac1c4 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -5,7 +5,6 @@ test_description='Test workflows involving pull request.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq PERL diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh index ed9dfd624c..8365907055 100755 --- a/t/t5200-update-server-info.sh +++ b/t/t5200-update-server-info.sh @@ -2,7 +2,6 @@ test_description='Test git update-server-info' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' 'test_commit file' @@ -39,4 +38,12 @@ test_expect_success 'info/refs updates when changes are made' ' ! test_cmp a b ' +test_expect_success 'midx does not create duplicate pack entries' ' + git repack -d --write-midx && + git repack -d && + grep ^P .git/objects/info/packs >packs && + uniq -d <packs >dups && + test_must_be_empty dups +' + test_done diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 4ad023c846..53dc3cbf90 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -5,7 +5,6 @@ test_description='git pack-object' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -156,6 +155,11 @@ test_expect_success 'pack without delta' ' check_deltas stderr = 0 ' +test_expect_success 'negative window clamps to 0' ' + git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr && + check_deltas stderr = 0 +' + test_expect_success 'pack-objects with bogus arguments' ' test_must_fail git pack-objects --window=0 test-1 blah blah <obj-list ' @@ -327,10 +331,8 @@ test_expect_success 'build pack index for an existing pack' ' git index-pack -o tmp.idx test-3.pack && cmp tmp.idx test-1-${packname_1}.idx && - git index-pack --promisor=message test-3.pack && + git index-pack test-3.pack && cmp test-3.idx test-1-${packname_1}.idx && - echo message >expect && - test_cmp expect test-3.promisor && cat test-2-${packname_2}.pack >test-3.pack && git index-pack -o tmp.idx test-2-${packname_2}.pack && @@ -630,9 +632,43 @@ test_expect_success 'prefetch objects' ' test_line_count = 1 donelines ' -test_expect_success 'negative window clamps to 0' ' - git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr && - check_deltas stderr = 0 -' +for hash in sha1 sha256 +do + test_expect_success "verify-pack with $hash packfile" ' + test_when_finished "rm -rf repo" && + git init --object-format=$hash repo && + test_commit -C repo initial && + git -C repo repack -ad && + git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx && + if test $hash = sha1 + then + nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx + else + # We have no way to identify the hash used by packfiles + # or indices, so we always fall back to SHA1. + nongit test_must_fail git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx && + # But with an explicit object format we should succeed. + nongit git verify-pack --object-format=$hash "$(pwd)"/repo/.git/objects/pack/*.idx + fi + ' + + test_expect_success "index-pack outside of a $hash repository" ' + test_when_finished "rm -rf repo" && + git init --object-format=$hash repo && + test_commit -C repo initial && + git -C repo repack -ad && + git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack && + if test $hash = sha1 + then + nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack + else + # We have no way to identify the hash used by packfiles + # or indices, so we always fall back to SHA1. + nongit test_must_fail git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack 2>err && + # But with an explicit object format we should succeed. + nongit git index-pack --object-format=$hash --verify "$(pwd)"/repo/.git/objects/pack/*.pack + fi + ' +done test_done diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh index 226490d60d..ff6b5159a3 100755 --- a/t/t5301-sliding-window.sh +++ b/t/t5301-sliding-window.sh @@ -5,7 +5,6 @@ test_description='mmap sliding window tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index d88e6f1691..413c99274c 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -5,7 +5,6 @@ test_description='pack index with 64-bit offsets and object CRC' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 61469ef4a6..de58ca654a 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -5,7 +5,6 @@ test_description='resilience to pack corruptions with redundant objects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Note: the test objects are created with knowledge of their pack encoding @@ -15,7 +14,7 @@ TEST_PASSES_SANITIZE_LEAK=true # 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2 # for base, such that blob_3 delta depth is 2; # -# 2) the bulk of object data is uncompressible so the text part remains +# 2) the bulk of object data is incompressible so the text part remains # visible; # # 3) object header is always 2 bytes. @@ -44,9 +43,14 @@ create_new_pack() { } do_repack() { + for f in $pack.* + do + mv $f "$(echo $f | sed -e 's/pack-/pack-corrupt-/')" || return 1 + done && pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" | git pack-objects $@ .git/objects/pack/pack) && - pack=".git/objects/pack/pack-${pack}" + pack=".git/objects/pack/pack-${pack}" && + rm -f .git/objects/pack/pack-corrupt-* } do_corrupt_object() { diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh index dc8fe55c82..44bd9ef45f 100755 --- a/t/t5305-include-tag.sh +++ b/t/t5305-include-tag.sh @@ -4,7 +4,6 @@ test_description='git pack-object --include-tag' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh TRASH=$(pwd) diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh index 0d50c6b4bc..805d60ff31 100755 --- a/t/t5306-pack-nobase.sh +++ b/t/t5306-pack-nobase.sh @@ -7,7 +7,6 @@ test_description='git-pack-object with missing base ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Create A-B chain diff --git a/t/t5307-pack-missing-commit.sh b/t/t5307-pack-missing-commit.sh index 1e02c305c4..fa4bc269fe 100755 --- a/t/t5307-pack-missing-commit.sh +++ b/t/t5307-pack-missing-commit.sh @@ -2,7 +2,6 @@ test_description='pack should notice missing commit objects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5308-pack-detect-duplicates.sh b/t/t5308-pack-detect-duplicates.sh index 655cafa054..0f84137867 100755 --- a/t/t5308-pack-detect-duplicates.sh +++ b/t/t5308-pack-detect-duplicates.sh @@ -2,7 +2,6 @@ test_description='handling of duplicate objects in incoming packfiles' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5309-pack-delta-cycles.sh b/t/t5309-pack-delta-cycles.sh index 4e910c5b9d..60fc710bac 100755 --- a/t/t5309-pack-delta-cycles.sh +++ b/t/t5309-pack-delta-cycles.sh @@ -2,7 +2,6 @@ test_description='test index-pack handling of delta cycles in packfiles' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index d7fd71360e..eabfcd7ff6 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -5,10 +5,6 @@ test_description='exercise basic bitmap functionality' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bitmap.sh -# t5310 deals only with single-pack bitmaps, so don't write MIDX bitmaps in -# their place. -GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 - # Likewise, allow individual tests to control whether or not they use # the boundary-based traversal. sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL @@ -506,6 +502,18 @@ test_expect_success 'boundary-based traversal is used when requested' ' done ' +test_expect_success 'left-right not confused by bitmap index' ' + git rev-list --left-right other...HEAD >expect && + git rev-list --use-bitmap-index --left-right other...HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'left-right count not confused by bitmap-index' ' + git rev-list --left-right --count other...HEAD >expect && + git rev-list --use-bitmap-index --left-right --count other...HEAD >actual && + test_cmp expect actual +' + test_bitmap_cases "pack.writeBitmapLookupTable" test_expect_success 'verify writing bitmap lookup table when enabled' ' diff --git a/t/t5311-pack-bitmaps-shallow.sh b/t/t5311-pack-bitmaps-shallow.sh index 4fe71fe8cd..012852c156 100755 --- a/t/t5311-pack-bitmaps-shallow.sh +++ b/t/t5311-pack-bitmaps-shallow.sh @@ -2,7 +2,6 @@ test_description='check bitmap operation with shallow repositories' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We want to create a situation where the shallow, grafted diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh index d8d2e30468..c37ef3818d 100755 --- a/t/t5312-prune-corruption.sh +++ b/t/t5312-prune-corruption.sh @@ -14,7 +14,6 @@ what currently happens. If that changes, these tests should be revisited. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'disable reflogs' ' diff --git a/t/t5313-pack-bounds-checks.sh b/t/t5313-pack-bounds-checks.sh index ceaa6700a2..5be01260d7 100755 --- a/t/t5313-pack-bounds-checks.sh +++ b/t/t5313-pack-bounds-checks.sh @@ -2,16 +2,15 @@ test_description='bounds-checking of access to mmapped on-disk file formats' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh clear_base () { test_when_finished 'restore_base' && - rm -f $base + rm -r -f $base } restore_base () { - cp base-backup/* .git/objects/pack/ + cp -r base-backup/* .git/objects/pack/ } do_pack () { @@ -64,9 +63,9 @@ test_expect_success 'set up base packfile and variables' ' git commit -m base && git repack -ad && base=$(echo .git/objects/pack/*) && - chmod +w $base && + chmod -R +w $base && mkdir base-backup && - cp $base base-backup/ && + cp -r $base base-backup/ && object=$(git rev-parse HEAD:file) ' diff --git a/t/t5314-pack-cycle-detection.sh b/t/t5314-pack-cycle-detection.sh index 82734b9a3c..9cd18c1e6b 100755 --- a/t/t5314-pack-cycle-detection.sh +++ b/t/t5314-pack-cycle-detection.sh @@ -50,7 +50,6 @@ will always find a delta for "file", because its lookup will always come immediately after the lookup for "dummy". ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Create a pack containing the tree $1 and blob $1:file, with diff --git a/t/t5315-pack-objects-compression.sh b/t/t5315-pack-objects-compression.sh index c80ea9e8b7..8bacd96275 100755 --- a/t/t5315-pack-objects-compression.sh +++ b/t/t5315-pack-objects-compression.sh @@ -2,7 +2,6 @@ test_description='pack-object compression configuration' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5316-pack-delta-depth.sh b/t/t5316-pack-delta-depth.sh index eb4ef3dda4..32cf422745 100755 --- a/t/t5316-pack-delta-depth.sh +++ b/t/t5316-pack-delta-depth.sh @@ -2,7 +2,6 @@ test_description='pack-objects breaks long cross-pack delta chains' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # This mirrors a repeated push setup: diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh index 79552d6ef7..501d715b9a 100755 --- a/t/t5317-pack-objects-filter-objects.sh +++ b/t/t5317-pack-objects-filter-objects.sh @@ -5,7 +5,6 @@ test_description='git pack-objects using object filtering' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Test blob:none filter. diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 2916c07e3c..f68f64cd85 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -2,7 +2,6 @@ test_description='commit graph' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-chunk.sh diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index ace5ac3b61..0f215ad2e8 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -1,10 +1,14 @@ #!/bin/sh test_description='multi-pack-indexes' + . ./test-lib.sh . "$TEST_DIRECTORY"/lib-chunk.sh +. "$TEST_DIRECTORY"/lib-midx.sh GIT_TEST_MULTI_PACK_INDEX=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 objdir=.git/objects HASH_LEN=$(test_oid rawsz) @@ -107,30 +111,6 @@ test_expect_success 'write midx with one v1 pack' ' midx_read_expect 1 18 4 $objdir ' -midx_git_two_modes () { - git -c core.multiPackIndex=false $1 >expect && - git -c core.multiPackIndex=true $1 >actual && - if [ "$2" = "sorted" ] - then - sort <expect >expect.sorted && - mv expect.sorted expect && - sort <actual >actual.sorted && - mv actual.sorted actual - fi && - test_cmp expect actual -} - -compare_results_with_midx () { - MSG=$1 - test_expect_success "check normal git operations: $MSG" ' - midx_git_two_modes "rev-list --objects --all" && - midx_git_two_modes "log --raw" && - midx_git_two_modes "count-objects --verbose" && - midx_git_two_modes "cat-file --batch-all-objects --batch-check" && - midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted - ' -} - test_expect_success 'write midx with one v2 pack' ' git pack-objects --index-version=2,0x40 $objdir/pack/test <obj-list && git multi-pack-index --object-dir=$objdir write && @@ -600,8 +580,7 @@ test_expect_success 'repack preserves multi-pack-index when creating packs' ' compare_results_with_midx "after repack" test_expect_success 'multi-pack-index and pack-bitmap' ' - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -c repack.writeBitmaps=true repack -ad && + git -c repack.writeBitmaps=true repack -ad && git multi-pack-index write && git rev-list --test-bitmap HEAD ' diff --git a/t/t5320-delta-islands.sh b/t/t5320-delta-islands.sh index 406363381f..2c961c7096 100755 --- a/t/t5320-delta-islands.sh +++ b/t/t5320-delta-islands.sh @@ -2,7 +2,6 @@ test_description='exercise delta islands' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # returns true iff $1 is a delta based on $2 diff --git a/t/t5321-pack-large-objects.sh b/t/t5321-pack-large-objects.sh index 70770fe274..51aaca1fcf 100755 --- a/t/t5321-pack-large-objects.sh +++ b/t/t5321-pack-large-objects.sh @@ -7,7 +7,6 @@ test_description='git pack-object with "large" deltas ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5322-pack-objects-sparse.sh b/t/t5322-pack-objects-sparse.sh index 770695c927..d39958c066 100755 --- a/t/t5322-pack-objects-sparse.sh +++ b/t/t5322-pack-objects-sparse.sh @@ -4,7 +4,6 @@ test_description='pack-objects object selection using sparse algorithm' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup repo' ' diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 77e91547ea..a32be3867d 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -2,7 +2,6 @@ test_description='split commit graph' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-chunk.sh @@ -203,7 +202,7 @@ then graph_git_behavior 'alternate: commit 13 vs 6' commits/13 origin/commits/6 "fork" fi -test_expect_success 'test merge stragety constants' ' +test_expect_success 'test merge strategy constants' ' git clone . merge-2 && ( cd merge-2 && diff --git a/t/t5325-reverse-index.sh b/t/t5325-reverse-index.sh index 431a603ca0..285c8b4a49 100755 --- a/t/t5325-reverse-index.sh +++ b/t/t5325-reverse-index.sh @@ -2,7 +2,6 @@ test_description='on-disk reverse index' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # The below tests want control over the 'pack.writeReverseIndex' setting diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh index 916da389b6..d27557b9b0 100755 --- a/t/t5326-multi-pack-bitmaps.sh +++ b/t/t5326-multi-pack-bitmaps.sh @@ -1,13 +1,14 @@ #!/bin/sh test_description='exercise basic multi-pack bitmap functionality' + . ./test-lib.sh . "${TEST_DIRECTORY}/lib-bitmap.sh" -# We'll be writing our own midx and bitmaps, so avoid getting confused by the +# We'll be writing our own MIDX, so avoid getting confused by the # automatic ones. GIT_TEST_MULTI_PACK_INDEX=0 -GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 # This test exercise multi-pack bitmap functionality where the object order is # stored and read from a special chunk within the MIDX, so use the default diff --git a/t/t5327-multi-pack-bitmaps-rev.sh b/t/t5327-multi-pack-bitmaps-rev.sh index e65e311cd7..9cac03a94b 100755 --- a/t/t5327-multi-pack-bitmaps-rev.sh +++ b/t/t5327-multi-pack-bitmaps-rev.sh @@ -5,10 +5,10 @@ test_description='exercise basic multi-pack bitmap functionality (.rev files)' . ./test-lib.sh . "${TEST_DIRECTORY}/lib-bitmap.sh" -# We'll be writing our own midx and bitmaps, so avoid getting confused by the -# automatic ones. +# We'll be writing our own MIDX, so avoid getting confused by the automatic +# ones. GIT_TEST_MULTI_PACK_INDEX=0 -GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 # Unlike t5326, this test exercise multi-pack bitmap functionality where the # object order is stored in a separate .rev file. diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh index fc6a242b56..a766a3e3f8 100755 --- a/t/t5328-commit-graph-64bit-time.sh +++ b/t/t5328-commit-graph-64bit-time.sh @@ -2,7 +2,6 @@ test_description='commit graph with 64-bit timestamps' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq TIME_IS_64BIT || ! test_have_prereq TIME_T_IS_64BIT diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh index fc5fedbe9b..b71a0aef40 100755 --- a/t/t5329-pack-objects-cruft.sh +++ b/t/t5329-pack-objects-cruft.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='cruft pack related pack-objects tests' + . ./test-lib.sh objdir=.git/objects @@ -688,7 +689,7 @@ test_expect_success 'cruft --local drops unreachable objects' ' test_when_finished "rm -fr alternate repo" && test_commit -C alternate base && - # Pack all objects in alterate so that the cruft repack in "repo" sees + # Pack all objects in alternate so that the cruft repack in "repo" sees # the object it dropped due to `--local` as packed. Otherwise this # object would not appear packed anywhere (since it is not packed in # alternate and likewise not part of the cruft pack in the other repo diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh index 5eb28f0512..313eadba98 100755 --- a/t/t5330-no-lazy-fetch-with-commit-graph.sh +++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh @@ -2,7 +2,6 @@ test_description='test for no lazy fetch with the commit-graph' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup: prepare a repository with a commit' ' @@ -38,9 +37,9 @@ test_expect_success 'fetch any commit from promisor with the usage of the commit git -C with-commit-graph config remote.origin.partialclonefilter blob:none && test_commit -C with-commit any-commit && anycommit=$(git -C with-commit rev-parse HEAD) && - GIT_TRACE="$(pwd)/trace.txt" \ + test_must_fail env GIT_TRACE="$(pwd)/trace.txt" \ git -C with-commit-graph fetch origin $anycommit 2>err && - ! grep "fatal: promisor-remote: unable to fork off fetch subprocess" err && + test_grep ! "fatal: promisor-remote: unable to fork off fetch subprocess" err && grep "git fetch origin" trace.txt >actual && test_line_count = 1 actual ' diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh index 2dcf1eecee..b48c0cbe8f 100755 --- a/t/t5331-pack-objects-stdin.sh +++ b/t/t5331-pack-objects-stdin.sh @@ -4,7 +4,6 @@ test_description='pack-objects --stdin' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh packed_objects () { diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh index ed823f37bc..57cad7708f 100755 --- a/t/t5332-multi-pack-reuse.sh +++ b/t/t5332-multi-pack-reuse.sh @@ -2,10 +2,11 @@ test_description='pack-objects multi-pack reuse' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bitmap.sh +GIT_TEST_MULTI_PACK_INDEX=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 objdir=.git/objects packdir=$objdir/pack @@ -29,20 +30,24 @@ test_pack_objects_reused_all () { : >trace2.txt && GIT_TRACE2_EVENT="$PWD/trace2.txt" \ git pack-objects --stdout --revs --all --delta-base-offset \ - >/dev/null && + >got.pack && test_pack_reused "$1" <trace2.txt && - test_packs_reused "$2" <trace2.txt + test_packs_reused "$2" <trace2.txt && + + git index-pack --strict -o got.idx got.pack } # test_pack_objects_reused <pack-reused> <packs-reused> test_pack_objects_reused () { : >trace2.txt && GIT_TRACE2_EVENT="$PWD/trace2.txt" \ - git pack-objects --stdout --revs >/dev/null && + git pack-objects --stdout --revs >got.pack && test_pack_reused "$1" <trace2.txt && - test_packs_reused "$2" <trace2.txt + test_packs_reused "$2" <trace2.txt && + + git index-pack --strict -o got.idx got.pack } test_expect_success 'preferred pack is reused for single-pack reuse' ' @@ -230,4 +235,49 @@ test_expect_success 'non-omitted delta in MIDX preferred pack' ' test_pack_objects_reused_all $(wc -l <expect) 1 ' +test_expect_success 'duplicate objects' ' + git init duplicate-objects && + ( + cd duplicate-objects && + + git config pack.allowPackReuse multi && + + test_commit base && + + git repack -a && + + git rev-parse HEAD^{tree} >in && + p="$(git pack-objects $packdir/pack <in)" && + + git multi-pack-index write --bitmap --preferred-pack=pack-$p.idx && + + objects_nr="$(git rev-list --count --all --objects)" && + packs_nr="$(find $packdir -type f -name "pack-*.pack" | wc -l)" && + + test_pack_objects_reused_all $objects_nr $packs_nr + ) +' + +test_expect_success 'duplicate objects with verbatim reuse' ' + git init duplicate-objects-verbatim && + ( + cd duplicate-objects-verbatim && + + git config pack.allowPackReuse multi && + + test_commit_bulk 64 && + + # take the first object from the main pack... + git show-index <$(ls $packdir/pack-*.idx) >obj.raw && + sort -nk1 <obj.raw | head -n1 | cut -d" " -f2 >in && + + # ...and create a separate pack containing just that object + p="$(git pack-objects $packdir/pack <in)" && + + git multi-pack-index write --bitmap --preferred-pack=pack-$p.idx && + + test_pack_objects_reused_all 192 2 + ) +' + test_done diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index f052f395a7..1dd6284756 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -390,4 +390,60 @@ test_expect_success 'pseudo-merge reuse' ' ) ' +test_expect_success 'empty pseudo-merge group' ' + git init pseudo-merge-empty-group && + ( + cd pseudo-merge-empty-group && + + # Ensure that a pseudo-merge group with no unstable + # commits does not generate an empty pseudo-merge + # bitmap. + git config bitmapPseudoMerge.empty.pattern refs/ && + + test_commit base && + git repack -adb && + + test-tool bitmap dump-pseudo-merges >merges && + test_line_count = 1 merges && + + test 0 -eq "$(grep -c commits=0 <merges)" + ) +' + +test_expect_success 'pseudo-merge closure' ' + git init pseudo-merge-closure && + ( + cd pseudo-merge-closure && + + test_commit A && + git repack -d && + + test_commit B && + + # Note that the contents of A is packed, but B is not. A + # (and the objects reachable from it) are thus visible + # to the MIDX, but the same is not true for B and its + # objects. + # + # Ensure that we do not attempt to create a pseudo-merge + # for B, depsite it matching the below pseudo-merge + # group pattern, as doing so would result in a failure + # to write a non-closed bitmap. + git config bitmapPseudoMerge.test.pattern refs/ && + git config bitmapPseudoMerge.test.threshold now && + + git multi-pack-index write --bitmap && + + test-tool bitmap dump-pseudo-merges >pseudo-merges && + test_line_count = 1 pseudo-merges && + + git rev-parse A >expect && + + test-tool bitmap list-commits >actual && + test_cmp expect actual && + test-tool bitmap dump-pseudo-merge-commits 0 >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t5334-incremental-multi-pack-index.sh b/t/t5334-incremental-multi-pack-index.sh new file mode 100755 index 0000000000..26257e5660 --- /dev/null +++ b/t/t5334-incremental-multi-pack-index.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +test_description='incremental multi-pack-index' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-midx.sh + +GIT_TEST_MULTI_PACK_INDEX=0 +export GIT_TEST_MULTI_PACK_INDEX + +objdir=.git/objects +packdir=$objdir/pack +midxdir=$packdir/multi-pack-index.d +midx_chain=$midxdir/multi-pack-index-chain + +test_expect_success 'convert non-incremental MIDX to incremental' ' + test_commit base && + git repack -ad && + git multi-pack-index write && + + test_path_is_file $packdir/multi-pack-index && + old_hash="$(midx_checksum $objdir)" && + + test_commit other && + git repack -d && + git multi-pack-index write --incremental && + + test_path_is_missing $packdir/multi-pack-index && + test_path_is_file $midx_chain && + test_line_count = 2 $midx_chain && + grep $old_hash $midx_chain +' + +compare_results_with_midx 'incremental MIDX' + +test_expect_success 'convert incremental to non-incremental' ' + test_commit squash && + git repack -d && + git multi-pack-index write && + + test_path_is_file $packdir/multi-pack-index && + test_dir_is_empty $midxdir +' + +compare_results_with_midx 'non-incremental MIDX conversion' + +test_done diff --git a/t/t5351-unpack-large-objects.sh b/t/t5351-unpack-large-objects.sh index 43cbcd5d49..d76eb4be93 100755 --- a/t/t5351-unpack-large-objects.sh +++ b/t/t5351-unpack-large-objects.sh @@ -5,7 +5,6 @@ test_description='git unpack-objects with large objects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh prepare_dest () { diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index d8cadeec73..723d1e17ec 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -4,6 +4,7 @@ # test_description='Test the update hook infrastructure.' + . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5402-post-merge-hook.sh b/t/t5402-post-merge-hook.sh index 46ebdfbeeb..915af2de95 100755 --- a/t/t5402-post-merge-hook.sh +++ b/t/t5402-post-merge-hook.sh @@ -7,7 +7,6 @@ test_description='Test the post-merge hook.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh index cfaae54739..978f240cda 100755 --- a/t/t5403-post-checkout-hook.sh +++ b/t/t5403-post-checkout-hook.sh @@ -7,7 +7,6 @@ test_description='Test the post-checkout hook.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh index 51737eeafe..cc07889667 100755 --- a/t/t5404-tracking-branches.sh +++ b/t/t5404-tracking-branches.sh @@ -5,7 +5,6 @@ test_description='tracking branch update checks for git push' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh index 1686ac13aa..11f03239a0 100755 --- a/t/t5405-send-pack-rewind.sh +++ b/t/t5405-send-pack-rewind.sh @@ -5,7 +5,6 @@ test_description='forced push to replace commit we do not have' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh index d6a9946633..dcbeb42082 100755 --- a/t/t5406-remote-rejects.sh +++ b/t/t5406-remote-rejects.sh @@ -2,7 +2,6 @@ test_description='remote push rejects are reported by client' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh index e99e728236..ad7f8c6f00 100755 --- a/t/t5407-post-rewrite-hook.sh +++ b/t/t5407-post-rewrite-hook.sh @@ -7,7 +7,6 @@ test_description='Test the post-rewrite hook.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5408-send-pack-stdin.sh b/t/t5408-send-pack-stdin.sh index e8737df6f9..526a675045 100755 --- a/t/t5408-send-pack-stdin.sh +++ b/t/t5408-send-pack-stdin.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='send-pack --stdin tests' + . ./test-lib.sh create_ref () { diff --git a/t/t5410-receive-pack-alternates.sh b/t/t5410-receive-pack-alternates.sh index 7a45d4c311..0b28e4e452 100755 --- a/t/t5410-receive-pack-alternates.sh +++ b/t/t5410-receive-pack-alternates.sh @@ -5,7 +5,6 @@ test_description='git receive-pack with alternate ref filtering' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5411/test-0034-report-ft.sh b/t/t5411/test-0034-report-ft.sh index 0e37535065..78d0b63876 100644 --- a/t/t5411/test-0034-report-ft.sh +++ b/t/t5411/test-0034-report-ft.sh @@ -10,7 +10,7 @@ test_expect_success "setup proc-receive hook (ft, $PROTOCOL)" ' # Refs of upstream : main(A) # Refs of workbench: main(A) tags/v123 # git push : refs/for/main/topic(B) -test_expect_success "proc-receive: fall throught, let receive-pack to execute ($PROTOCOL)" ' +test_expect_success "proc-receive: fall through, let receive-pack to execute ($PROTOCOL)" ' git -C workbench push origin \ $B:refs/for/main/topic \ >out 2>&1 && diff --git a/t/t5411/test-0035-report-ft--porcelain.sh b/t/t5411/test-0035-report-ft--porcelain.sh index b9a05181f1..df5fc212be 100644 --- a/t/t5411/test-0035-report-ft--porcelain.sh +++ b/t/t5411/test-0035-report-ft--porcelain.sh @@ -10,7 +10,7 @@ test_expect_success "setup proc-receive hook (fall-through, $PROTOCOL/porcelain) # Refs of upstream : main(A) # Refs of workbench: main(A) tags/v123 # git push : refs/for/main/topic(B) -test_expect_success "proc-receive: fall throught, let receive-pack to execute ($PROTOCOL/porcelain)" ' +test_expect_success "proc-receive: fall through, let receive-pack to execute ($PROTOCOL/porcelain)" ' git -C workbench push --porcelain origin \ $B:refs/for/main/topic \ >out 2>&1 && diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 585ea0ee16..2677cd5faa 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -417,7 +417,7 @@ test_expect_success 'in_vain not triggered before first ACK' ' test_grep "remote: Total 3 " log ' -test_expect_success 'in_vain resetted upon ACK' ' +test_expect_success 'in_vain reset upon ACK' ' test_when_finished rm -f log trace2 && rm -rf myserver myclient && git init myserver && @@ -773,7 +773,7 @@ do # file with scheme for p in file do - test_expect_success !MINGW "fetch-pack --diag-url $p://$h/$r" ' + test_expect_success !WINDOWS "fetch-pack --diag-url $p://$h/$r" ' check_prot_path $p://$h/$r $p "/$r" ' test_expect_success MINGW "fetch-pack --diag-url $p://$h/$r" ' @@ -783,7 +783,7 @@ do check_prot_path $p:///$r $p "/$r" ' # No "/~" -> "~" conversion for file - test_expect_success !MINGW "fetch-pack --diag-url $p://$h/~$r" ' + test_expect_success !WINDOWS "fetch-pack --diag-url $p://$h/~$r" ' check_prot_path $p://$h/~$r $p "/~$r" ' test_expect_success MINGW "fetch-pack --diag-url $p://$h/~$r" ' @@ -805,11 +805,17 @@ do p=ssh for h in host [::1] do - test_expect_success "fetch-pack --diag-url $h:$r" ' + expectation="success" + if test_have_prereq CYGWIN && test "$h" = "[::1]" + then + expectation="failure" + fi + + test_expect_$expectation "fetch-pack --diag-url $h:$r" ' check_prot_host_port_path $h:$r $p "$h" NONE "$r" ' # Do "/~" -> "~" conversion - test_expect_success "fetch-pack --diag-url $h:/~$r" ' + test_expect_$expectation "fetch-pack --diag-url $h:/~$r" ' check_prot_host_port_path $h:/~$r $p "$h" NONE "~$r" ' done @@ -919,6 +925,13 @@ test_expect_success 'fetch exclude tag one' ' test_cmp expected actual ' +test_expect_success 'fetch exclude tag one as revision' ' + test_when_finished rm -f rev err && + git -C shallow-exclude rev-parse one >rev && + test_must_fail git -C shallow12 fetch --shallow-exclude $(cat rev) origin 2>err && + grep "deepen-not is not a ref:" err +' + test_expect_success 'fetching deepen' ' test_create_repo shallow-deepen && ( diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh index 7b3ff21b98..b160f8b7fb 100755 --- a/t/t5502-quickfetch.sh +++ b/t/t5502-quickfetch.sh @@ -5,7 +5,6 @@ test_description='test quickfetch from local' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh index 5ebbaa4896..195fc64dd4 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -5,7 +5,6 @@ test_description='test automatic tag following' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # End state of the repository: diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 138e6778a4..8212a70be8 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -4,7 +4,6 @@ test_description='fetch/receive strict mode' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup and inject "corrupt or missing" object' ' @@ -171,7 +170,7 @@ test_expect_success 'fsck with invalid or bogus skipList input' ' test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && test_grep "could not open.*: does-not-exist" err && test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && - test_grep "invalid object name: \[core\]" err + test_grep "invalid object name: " err ' test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' ' @@ -234,7 +233,7 @@ test_expect_success 'push with receive.fsck.skipList' ' test_grep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config receive.fsck.skipList config && test_must_fail git push --porcelain dst bogus 2>err && - test_grep "invalid object name: \[core\]" err && + test_grep "invalid object name: " err && git --git-dir=dst/.git config receive.fsck.skipList SKIP && git push --porcelain dst bogus @@ -263,7 +262,7 @@ test_expect_success 'fetch with fetch.fsck.skipList' ' test_grep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && - test_grep "invalid object name: \[core\]" err && + test_grep "invalid object name: " err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && git --git-dir=dst/.git fetch "file://$(pwd)" $refspec diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh index 0e176175a3..16e9a1bc2f 100755 --- a/t/t5506-remote-groups.sh +++ b/t/t5506-remote-groups.sh @@ -4,7 +4,6 @@ test_description='git remote group handling' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh mark() { diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh index c6a6957c50..a41d5b370b 100755 --- a/t/t5507-remote-environment.sh +++ b/t/t5507-remote-environment.sh @@ -2,7 +2,6 @@ test_description='check environment showed to remote side of transports' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up "remote" push situation' ' diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh index 31553b48df..095df1a753 100755 --- a/t/t5509-fetch-push-namespaces.sh +++ b/t/t5509-fetch-push-namespaces.sh @@ -95,6 +95,7 @@ test_expect_success 'hide namespaced refs with transfer.hideRefs' ' ' test_expect_success 'check that transfer.hideRefs does not match unstripped refs' ' + git -C pushee pack-refs --all && GIT_NAMESPACE=namespace \ git -C pushee -c transfer.hideRefs=refs/namespaces/namespace/refs/tags \ ls-remote "ext::git %s ." >actual && @@ -122,6 +123,14 @@ test_expect_success 'try to update a ref that is not hidden' ' git -C original push pushee-namespaced main ' +test_expect_success 'git-receive-pack(1) with transfer.hideRefs does not match unstripped refs during advertisement' ' + git -C pushee update-ref refs/namespaces/namespace/refs/heads/foo/1 refs/namespaces/namespace/refs/heads/main && + git -C pushee pack-refs --all && + test_config -C pushee transfer.hideRefs refs/namespaces/namespace/refs/heads/foo && + GIT_TRACE_PACKET="$(pwd)/trace" git -C original push pushee-namespaced main && + test_grep refs/heads/foo/1 trace +' + test_expect_success 'try to update a hidden full ref' ' test_config -C pushee transfer.hideRefs "^refs/namespaces/namespace/refs/heads/main" && test_must_fail git -C original push pushee-namespaced main diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh index fc55681a3f..be025b90f9 100755 --- a/t/t5511-refspec.sh +++ b/t/t5511-refspec.sh @@ -2,7 +2,6 @@ test_description='refspec parsing' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_refspec () { diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index d687d824d1..3a67992a7d 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -5,7 +5,6 @@ test_description='git ls-remote' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh generate_references () { @@ -403,4 +402,18 @@ test_expect_success 'v0 clients can handle multiple symrefs' ' test_cmp expect actual ' +test_expect_success 'helper with refspec capability fails gracefully' ' + mkdir test-bin && + write_script test-bin/git-remote-foo <<-EOF && + read capabilities + echo import + echo refspec ${SQ}*:*${SQ} + EOF + ( + PATH="$PWD/test-bin:$PATH" && + export PATH && + test_must_fail nongit git ls-remote foo::bar + ) +' + test_done diff --git a/t/t5513-fetch-track.sh b/t/t5513-fetch-track.sh index c46c4dbaef..65d1e05bd6 100755 --- a/t/t5513-fetch-track.sh +++ b/t/t5513-fetch-track.sh @@ -2,7 +2,6 @@ test_description='fetch follows remote-tracking branches correctly' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh index 579872c258..25772c85c5 100755 --- a/t/t5514-fetch-multiple.sh +++ b/t/t5514-fetch-multiple.sh @@ -5,7 +5,6 @@ test_description='fetch --all works correctly' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh setup_repository () { diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index c100a809c5..320d26796d 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -14,7 +14,6 @@ export GIT_TEST_PROTOCOL_VERSION GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh build_script () { diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh index 6d4944a728..a448e169bd 100755 --- a/t/t5517-push-mirror.sh +++ b/t/t5517-push-mirror.sh @@ -5,7 +5,6 @@ test_description='pushing to a mirror repository' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh D=$(pwd) diff --git a/t/t5518-fetch-exit-status.sh b/t/t5518-fetch-exit-status.sh index c13120088f..5c4ac2556e 100755 --- a/t/t5518-fetch-exit-status.sh +++ b/t/t5518-fetch-exit-status.sh @@ -8,7 +8,6 @@ test_description='fetch exit status test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 1098cbd0a1..47534f1062 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -5,7 +5,6 @@ test_description='pulling into void' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh modify () { diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index db00c4336b..5e420c208c 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -5,7 +5,6 @@ test_description='pull options' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh index cc5496e28f..9fb73a8c3e 100755 --- a/t/t5522-pull-symlink.sh +++ b/t/t5522-pull-symlink.sh @@ -2,7 +2,6 @@ test_description='pulling from symlinked subdir' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # The scenario we are building: diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh index 1f859ade16..22d3e1162c 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -4,7 +4,6 @@ test_description='push with --set-upstream' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -124,14 +123,14 @@ test_expect_success TTY 'push --no-progress suppresses progress' ' test_expect_success TTY 'quiet push' ' ensure_fresh_upstream && - test_terminal git push --quiet --no-progress upstream main 2>&1 | tee output && + test_terminal git push --quiet --no-progress upstream main >output 2>&1 && test_must_be_empty output ' test_expect_success TTY 'quiet push -u' ' ensure_fresh_upstream && - test_terminal git push --quiet -u --no-progress upstream main 2>&1 | tee output && + test_terminal git push --quiet -u --no-progress upstream main >output 2>&1 && test_must_be_empty output ' diff --git a/t/t5524-pull-msg.sh b/t/t5524-pull-msg.sh index 56716e29dd..b2be3605f5 100755 --- a/t/t5524-pull-msg.sh +++ b/t/t5524-pull-msg.sh @@ -2,7 +2,6 @@ test_description='git pull message generation' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh dollar='$Dollar' diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh index 3a28f1ded5..45815f7378 100755 --- a/t/t5525-fetch-tagopt.sh +++ b/t/t5525-fetch-tagopt.sh @@ -2,7 +2,6 @@ test_description='tagopt variable affects "git fetch" and is overridden by commandline.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh setup_clone () { diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh index 98ece27c6a..e2770e4541 100755 --- a/t/t5527-fetch-odd-refs.sh +++ b/t/t5527-fetch-odd-refs.sh @@ -4,7 +4,6 @@ test_description='test fetching of oddly-named refs' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # afterwards we will have: diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index bc2bada34c..2bd8759a68 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -4,7 +4,6 @@ test_description='check various push.default settings' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup bare remotes' ' @@ -147,7 +146,7 @@ test_expect_success 'push from/to new branch fails with upstream and simple ' ' # - the default push succeeds # # A previous test expected this to fail, but for the wrong reasons: -# it expected a fail becaause the branch is new and cannot be pushed, but +# it expected to fail because the branch is new and cannot be pushed, but # in fact it was failing because of an ambiguous remote # test_expect_failure 'push from/to new branch fails with matching ' ' diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh index 17d7257892..80b06a0cd2 100755 --- a/t/t5529-push-errors.sh +++ b/t/t5529-push-errors.sh @@ -5,7 +5,6 @@ test_description='detect some push errors early (before contacting remote)' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup commits' ' diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 7172780d55..558eedf25a 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -2,7 +2,6 @@ test_description='errors in upload-pack' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh D=$(pwd) diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index f3fff55744..05debd1134 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -203,7 +203,7 @@ test_expect_success 'push recurse-submodules last one wins on command line' ' cd work/gar/bage && >recurse-check-on-command-line-overriding-earlier-command-line && git add recurse-check-on-command-line-overriding-earlier-command-line && - git commit -m "Recurse on command-line overridiing earlier command-line junk" + git commit -m "Recurse on command-line overriding earlier command-line junk" ) && ( cd work && diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh index d664912799..3755822629 100755 --- a/t/t5532-fetch-proxy.sh +++ b/t/t5532-fetch-proxy.sh @@ -2,7 +2,6 @@ test_description='fetching via git:// using core.gitproxy' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup remote repo' ' diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh index 7122af7fdb..e8f6d233ff 100755 --- a/t/t5535-fetch-push-symref.sh +++ b/t/t5535-fetch-push-symref.sh @@ -2,7 +2,6 @@ test_description='avoiding conflicting update through symref aliasing' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 479d103469..04b47ad84a 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -5,7 +5,6 @@ test_description='pushing to a repository using the atomic push option' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh mk_repo_pair () { diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh index 1a9e14bbcc..89147a052e 100755 --- a/t/t5544-pack-objects-hook.sh +++ b/t/t5544-pack-objects-hook.sh @@ -2,7 +2,6 @@ test_description='test custom script in place of pack-objects' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create some history to fetch' ' diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh index 9fc9ba552f..f1e61c9f09 100755 --- a/t/t5546-receive-limits.sh +++ b/t/t5546-receive-limits.sh @@ -2,7 +2,6 @@ test_description='check receive input limits' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Let's run tests with different unpack limits: 1 and 10000 diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh index 9f899b8c7d..0798ddab02 100755 --- a/t/t5547-push-quarantine.sh +++ b/t/t5547-push-quarantine.sh @@ -2,7 +2,6 @@ test_description='check quarantine of objects during push' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create picky dest repo' ' diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index ea8e48f627..21795a19bf 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -306,6 +306,14 @@ test_expect_success 'fetch notices corrupt idx' ' ) ' +# usage: count_fetches <nr> <extension> <trace_file> +count_fetches () { + # ignore grep exit code; it may return non-zero if we are expecting no + # matches + grep "GET .*objects/pack/pack-[a-z0-9]*.$2" "$3" >trace.count + test_line_count = "$1" trace.count +} + test_expect_success 'fetch can handle previously-fetched .idx files' ' git checkout --orphan branch1 && echo base >file && @@ -320,8 +328,14 @@ test_expect_success 'fetch can handle previously-fetched .idx files' ' git push "$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git branch2 && git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git repack -d && git --bare init clone_packed_branches.git && - git --git-dir=clone_packed_branches.git fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch1:branch1 && - git --git-dir=clone_packed_branches.git fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch2:branch2 + GIT_TRACE_CURL=$PWD/one.trace git --git-dir=clone_packed_branches.git \ + fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch1:branch1 && + count_fetches 2 idx one.trace && + count_fetches 1 pack one.trace && + GIT_TRACE_CURL=$PWD/two.trace git --git-dir=clone_packed_branches.git \ + fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch2:branch2 && + count_fetches 1 idx two.trace && + count_fetches 1 pack two.trace ' test_expect_success 'did not use upload-pack service' ' @@ -343,12 +357,12 @@ test_expect_success 'git client shows text/plain with a charset' ' grep "this is the error message" stderr ' -test_expect_success 'http error messages are reencoded' ' +test_expect_success ICONV 'http error messages are reencoded' ' test_must_fail git clone "$HTTPD_URL/error/utf16" 2>stderr && grep "this is the error message" stderr ' -test_expect_success 'reencoding is robust to whitespace oddities' ' +test_expect_success ICONV 'reencoding is robust to whitespace oddities' ' test_must_fail git clone "$HTTPD_URL/error/odd-spacing" 2>stderr && grep "this is the error message" stderr ' @@ -506,4 +520,14 @@ test_expect_success 'fetching via http alternates works' ' git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git" ' +test_expect_success 'dumb http can fetch index v1' ' + server=$HTTPD_DOCUMENT_ROOT_PATH/idx-v1.git && + git init --bare "$server" && + git -C "$server" --work-tree=. commit --allow-empty -m foo && + git -C "$server" -c pack.indexVersion=1 gc && + + git clone "$HTTPD_URL/dumb/idx-v1.git" && + git -C idx-v1 fsck +' + test_done diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 7b5ab0eae1..ceb3336a5c 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -186,6 +186,28 @@ test_expect_success 'clone from password-protected repository' ' test_cmp expect actual ' +test_expect_success 'credential.interactive=false skips askpass' ' + set_askpass bogus nonsense && + ( + GIT_TRACE2_EVENT="$(pwd)/interactive-true" && + export GIT_TRACE2_EVENT && + test_must_fail git clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-true-dir && + test_region credential interactive interactive-true && + + GIT_TRACE2_EVENT="$(pwd)/interactive-false" && + export GIT_TRACE2_EVENT && + test_must_fail git -c credential.interactive=false \ + clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-false-dir && + test_region ! credential interactive interactive-false && + + GIT_TRACE2_EVENT="$(pwd)/interactive-never" && + export GIT_TRACE2_EVENT && + test_must_fail git -c credential.interactive=never \ + clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-never-dir && + test_region ! credential interactive interactive-never + ) +' + test_expect_success 'clone from auth-only-for-push repository' ' echo two >expect && set_askpass wrong && diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh index b55a9f65e6..eeddb85b1d 100755 --- a/t/t5552-skipping-fetch-negotiator.sh +++ b/t/t5552-skipping-fetch-negotiator.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test skipping fetch negotiator' + . ./test-lib.sh test_expect_success 'fetch.negotiationalgorithm config' ' diff --git a/t/t5554-noop-fetch-negotiator.sh b/t/t5554-noop-fetch-negotiator.sh index 06991e8e8a..17e73b606d 100755 --- a/t/t5554-noop-fetch-negotiator.sh +++ b/t/t5554-noop-fetch-negotiator.sh @@ -2,7 +2,6 @@ test_description='test noop fetch negotiator' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'noop negotiator does not emit any "have"' ' diff --git a/t/t5555-http-smart-common.sh b/t/t5555-http-smart-common.sh index 3dcb3340a3..e47ea1ad10 100755 --- a/t/t5555-http-smart-common.sh +++ b/t/t5555-http-smart-common.sh @@ -2,7 +2,6 @@ test_description='test functionality common to smart fetch & push' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5557-http-get.sh b/t/t5557-http-get.sh index 76a4bbd16a..67fcc23f11 100755 --- a/t/t5557-http-get.sh +++ b/t/t5557-http-get.sh @@ -2,7 +2,6 @@ test_description='test downloading a file by URL' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh index cd05321e17..3816ed5058 100755 --- a/t/t5558-clone-bundle-uri.sh +++ b/t/t5558-clone-bundle-uri.sh @@ -945,7 +945,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' ' --bundle-uri="$HTTPD_URL/bundle-list" \ "$HTTPD_URL/smart/fetch.git" download-3 && - # As long as we have continguous successful downloads, + # As long as we have contiguous successful downloads, # we _do_ set these configs. test_cmp_config -C download-3 "$HTTPD_URL/bundle-list" fetch.bundleuri && test_cmp_config -C download-3 3 fetch.bundlecreationtoken && @@ -1189,7 +1189,7 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' ' GIT_TRACE2_EVENT="$(pwd)/trace-fetch-3.txt" \ git -C fetch-3 fetch origin && - # As long as we have continguous successful downloads, + # As long as we have contiguous successful downloads, # we _do_ set the maximum creation token. test_cmp_config -C fetch-3 6 fetch.bundlecreationtoken && diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh index f75068de64..d30cf4f5b8 100755 --- a/t/t5560-http-backend-noserver.sh +++ b/t/t5560-http-backend-noserver.sh @@ -4,7 +4,6 @@ test_description='test git-http-backend-noserver' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY" diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh index e1d3b8caed..9c57d84315 100755 --- a/t/t5561-http-backend.sh +++ b/t/t5561-http-backend.sh @@ -4,7 +4,6 @@ test_description='test git-http-backend' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh index 7ee9858a78..f3b158274c 100755 --- a/t/t5562-http-backend-content-length.sh +++ b/t/t5562-http-backend-content-length.sh @@ -2,7 +2,6 @@ test_description='test git-http-backend respects CONTENT_LENGTH' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_lazy_prereq GZIP 'gzip --version' diff --git a/t/t5562/invoke-with-content-length.pl b/t/t5562/invoke-with-content-length.pl index 9babb9a375..211e29fade 100644 --- a/t/t5562/invoke-with-content-length.pl +++ b/t/t5562/invoke-with-content-length.pl @@ -1,4 +1,4 @@ -use 5.008001; +require v5.26; use strict; use warnings; diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh index ba03f6a09f..317f33af5a 100755 --- a/t/t5563-simple-http-auth.sh +++ b/t/t5563-simple-http-auth.sh @@ -2,7 +2,6 @@ test_description='test http auth header and credential helper interop' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh diff --git a/t/t5564-http-proxy.sh b/t/t5564-http-proxy.sh index bb35b87071..b27e481f95 100755 --- a/t/t5564-http-proxy.sh +++ b/t/t5564-http-proxy.sh @@ -2,7 +2,6 @@ test_description="test fetching through http proxy" -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh @@ -39,4 +38,59 @@ test_expect_success 'clone can prompt for proxy password' ' expect_askpass pass proxuser ' +start_socks() { + mkfifo socks_output && + { + "$PERL_PATH" "$TEST_DIRECTORY/socks4-proxy.pl" "$1" >socks_output & + echo $! > "$TRASH_DIRECTORY/socks.pid" + } && + read line <socks_output && + test "$line" = ready +} + +# The %30 tests that the correct amount of percent-encoding is applied to the +# proxy string passed to curl. +test_lazy_prereq SOCKS_PROXY ' + test_have_prereq PERL && + start_socks "$TRASH_DIRECTORY/%30.sock" +' + +test_atexit ' + test ! -e "$TRASH_DIRECTORY/socks.pid" || + kill "$(cat "$TRASH_DIRECTORY/socks.pid")" +' + +# The below tests morally ought to be gated on a prerequisite that Git is +# linked with a libcurl that supports Unix socket paths for proxies (7.84 or +# later), but this is not easy to test right now. Instead, we || the tests with +# this function. +old_libcurl_error() { + grep -Fx "fatal: libcurl 7.84 or later is required to support paths in proxy URLs" "$1" +} + +test_expect_success SOCKS_PROXY 'clone via Unix socket' ' + test_when_finished "rm -rf clone" && + test_config_global http.proxy "socks4://localhost$PWD/%2530.sock" && { + { + GIT_TRACE_CURL=$PWD/trace git clone "$HTTPD_URL/smart/repo.git" clone 2>err && + grep -i "SOCKS4 request granted" trace + } || + old_libcurl_error err + } +' + +test_expect_success 'Unix socket requires socks*:' - <<\EOT + ! git clone -c http.proxy=localhost/path https://example.com/repo.git 2>err && { + grep -Fx "fatal: Invalid proxy URL 'localhost/path': only SOCKS proxies support paths" err || + old_libcurl_error err + } +EOT + +test_expect_success 'Unix socket requires localhost' - <<\EOT + ! git clone -c http.proxy=socks4://127.0.0.1/path https://example.com/repo.git 2>err && { + grep -Fx "fatal: Invalid proxy URL 'socks4://127.0.0.1/path': host must be localhost if a path is present" err || + old_libcurl_error err + } +EOT + test_done diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh index c5f08b6799..8df4001b72 100755 --- a/t/t5570-git-daemon.sh +++ b/t/t5570-git-daemon.sh @@ -4,10 +4,34 @@ test_description='test fetching over git protocol' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-git-daemon.sh + +test_expect_success 'daemon rejects invalid --init-timeout values' ' + for arg in "3a" "-3" + do + test_must_fail git daemon --init-timeout="$arg" 2>err && + test_grep "fatal: invalid init-timeout ${SQ}$arg${SQ}, expecting a non-negative integer" err || + return 1 + done +' + +test_expect_success 'daemon rejects invalid --timeout values' ' + for arg in "3a" "-3" + do + test_must_fail git daemon --timeout="$arg" 2>err && + test_grep "fatal: invalid timeout ${SQ}$arg${SQ}, expecting a non-negative integer" err || + return 1 + done +' + +test_expect_success 'daemon rejects invalid --max-connections values' ' + arg='3a' && + test_must_fail git daemon --max-connections=3a 2>err && + test_grep "fatal: invalid max-connections ${SQ}$arg${SQ}, expecting an integer" err +' + start_git_daemon check_verbose_connect () { diff --git a/t/t5571-pre-push-hook.sh b/t/t5571-pre-push-hook.sh index 448134c4bf..a11b20e378 100755 --- a/t/t5571-pre-push-hook.sh +++ b/t/t5571-pre-push-hook.sh @@ -4,7 +4,6 @@ test_description='check pre-push hooks' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh index 51744521f7..f7650e8475 100755 --- a/t/t5572-pull-submodule.sh +++ b/t/t5572-pull-submodule.sh @@ -229,6 +229,7 @@ test_expect_success 'branch has no merge base with remote-tracking counterpart' test_create_repo a-submodule && test_commit -C a-submodule foo && + test_commit -C a-submodule bar && test_create_repo parent && git -C parent submodule add "$(pwd)/a-submodule" && @@ -245,4 +246,23 @@ test_expect_success 'branch has no merge base with remote-tracking counterpart' git -C child pull --recurse-submodules --rebase ' +test_expect_success 'fetch submodule remote of different name from superproject' ' + git -C child remote rename origin o1 && + git -C child submodule update --init && + + # Needs to create unreachable commit from current master branch. + git -C a-submodule checkout -b newmain HEAD^ && + test_commit -C a-submodule echo && + test_commit -C a-submodule moreecho && + subc=$(git -C a-submodule rev-parse --short HEAD) && + + git -C parent/a-submodule fetch && + git -C parent/a-submodule checkout "$subc" && + git -C parent commit -m "update submodule" a-submodule && + git -C a-submodule reset --hard HEAD^^ && + + git -C child pull --no-recurse-submodules && + git -C child submodule update +' + test_done diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh index ab05f38a99..a76b54d7de 100755 --- a/t/t5573-pull-verify-signatures.sh +++ b/t/t5573-pull-verify-signatures.sh @@ -2,7 +2,6 @@ test_description='pull signature verification tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" diff --git a/t/t5580-unc-paths.sh b/t/t5580-unc-paths.sh index d7537a162b..65ef1a3628 100755 --- a/t/t5580-unc-paths.sh +++ b/t/t5580-unc-paths.sh @@ -4,7 +4,6 @@ test_description='various Windows-only path tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if test_have_prereq CYGWIN diff --git a/t/t5581-http-curl-verbose.sh b/t/t5581-http-curl-verbose.sh index 724f610054..cded79c16b 100755 --- a/t/t5581-http-curl-verbose.sh +++ b/t/t5581-http-curl-verbose.sh @@ -4,7 +4,6 @@ test_description='test GIT_CURL_VERBOSE' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd diff --git a/t/t5582-fetch-negative-refspec.sh b/t/t5582-fetch-negative-refspec.sh index 7a80e47c2b..ae32f8178a 100755 --- a/t/t5582-fetch-negative-refspec.sh +++ b/t/t5582-fetch-negative-refspec.sh @@ -282,4 +282,8 @@ test_expect_success '--prefetch succeeds when refspec becomes empty' ' git -C one fetch --prefetch ' +test_expect_success '--prefetch succeeds with empty command line refspec' ' + git -C one fetch --prefetch origin +refs/tags/extra +' + test_done diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh index 320f49c753..e7e1b6dab6 100755 --- a/t/t5583-push-branches.sh +++ b/t/t5583-push-branches.sh @@ -5,7 +5,6 @@ test_description='check the consisitency of behavior of --all and --branches' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh delete_refs() { diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh index c814afa565..34b3df4027 100755 --- a/t/t5600-clone-fail-cleanup.sh +++ b/t/t5600-clone-fail-cleanup.sh @@ -13,7 +13,6 @@ Unless the directory already exists, in which case we clean up only what we wrote. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh corrupt_repo () { diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 5d7ea147f1..d0c18660e3 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -530,19 +530,30 @@ do ' done +# Parsing of paths that look like IPv6 addresses is broken on Cygwin. +expectation_for_ipv6_tests=success +if test_have_prereq CYGWIN +then + expectation_for_ipv6_tests=failure +fi + #ipv6 for repo in rep rep/home/project 123 do - test_expect_success "clone [::1]:$repo" ' + test_expect_$expectation_for_ipv6_tests "clone [::1]:$repo" ' test_clone_url [::1]:$repo ::1 "$repo" ' done -#home directory -test_expect_success "clone host:/~repo" ' + +# Home directory. All tests that use "~repo" are broken in our CI job when the +# leak sanitizer is enabled. It seems like either a bug in the sanitizer or in +# glibc, but when executing getpwnam(3p) with an invalid username we eventually +# start recursing in a call to free(3p), until bust the stack and segfault. +test_expect_success !SANITIZE_LEAK "clone host:/~repo" ' test_clone_url host:/~repo host "~repo" ' -test_expect_success "clone [::1]:/~repo" ' +test_expect_$expectation_for_ipv6_tests !SANITIZE_LEAK "clone [::1]:/~repo" ' test_clone_url [::1]:/~repo ::1 "~repo" ' @@ -562,9 +573,9 @@ do test_clone_url "ssh://host.xz$tcol/home/user/repo" host.xz /home/user/repo ' # from home directory - test_expect_success "clone ssh://host.xz$tcol/~repo" ' - test_clone_url "ssh://host.xz$tcol/~repo" host.xz "~repo" -' + test_expect_success !SANITIZE_LEAK "clone ssh://host.xz$tcol/~repo" ' + test_clone_url "ssh://host.xz$tcol/~repo" host.xz "~repo" + ' done # with port number @@ -573,7 +584,7 @@ test_expect_success 'clone ssh://host.xz:22/home/user/repo' ' ' # from home directory with port number -test_expect_success 'clone ssh://host.xz:22/~repo' ' +test_expect_success !SANITIZE_LEAK 'clone ssh://host.xz:22/~repo' ' test_clone_url "ssh://host.xz:22/~repo" "-p 22 host.xz" "~repo" ' @@ -590,8 +601,8 @@ done for tuah in ::1 [::1] user@::1 user@[::1] [user@::1] do euah=$(echo $tuah | tr -d "[]") - test_expect_success "clone ssh://$tuah/~repo" " - test_clone_url ssh://$tuah/~repo $euah '~repo' + test_expect_success !SANITIZE_LEAK "clone ssh://$tuah/~repo" " + test_clone_url ssh://$tuah/~repo $euah '~repo' " done @@ -608,8 +619,8 @@ done for tuah in [::1] user@[::1] [user@::1] do euah=$(echo $tuah | tr -d "[]") - test_expect_success "clone ssh://$tuah:22/~repo" " - test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo' + test_expect_success !SANITIZE_LEAK "clone ssh://$tuah:22/~repo" " + test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo' " done diff --git a/t/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh index 56329aa160..cbcceab9d5 100755 --- a/t/t5602-clone-remote-exec.sh +++ b/t/t5602-clone-remote-exec.sh @@ -2,7 +2,6 @@ test_description=clone -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5603-clone-dirname.sh b/t/t5603-clone-dirname.sh index 8ca1f09423..80eb4e04f8 100755 --- a/t/t5603-clone-dirname.sh +++ b/t/t5603-clone-dirname.sh @@ -2,7 +2,6 @@ test_description='check output directory names used by git-clone' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # we use a fake ssh wrapper that ignores the arguments diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 9b32db8478..470bfb610c 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -7,7 +7,6 @@ test_description='test clone --reference' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh base_dir=$(pwd) @@ -131,7 +130,7 @@ test_expect_success 'cloning with multiple references drops duplicates' ' test_expect_success 'clone with reference from a tagged repository' ' ( - cd A && git tag -a -m tagged HEAD + cd A && git tag -a -m tagged foo ) && git clone --reference=A A I ' @@ -156,10 +155,10 @@ test_expect_success 'fetch with incomplete alternates' ' git remote add J "file://$base_dir/J" && GIT_TRACE_PACKET=$U.K git fetch J ) && - main_object=$(cd A && git for-each-ref --format="%(objectname)" refs/heads/main) && + main_object=$(git -C A rev-parse --verify refs/heads/main) && test -s "$U.K" && ! grep " want $main_object" "$U.K" && - tag_object=$(cd A && git for-each-ref --format="%(objectname)" refs/tags/HEAD) && + tag_object=$(git -C A rev-parse --verify refs/tags/foo) && ! grep " want $tag_object" "$U.K" ' diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index d9a320abd2..4605703496 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -4,7 +4,6 @@ test_description='test local clone' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh repo_is_hardlinked() { @@ -154,6 +153,16 @@ test_expect_success 'cloning a local path with --no-local does not hardlink' ' ! repo_is_hardlinked force-nonlocal ' +test_expect_success 'cloning a local path with --no-local from a different user succeeds' ' + git clone --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ + --no-local a nonlocal-otheruser 2>err && + ! repo_is_hardlinked nonlocal-otheruser && + # Verify that this is a git repository. + git -C nonlocal-otheruser rev-parse --show-toplevel && + ! test_grep "detected dubious ownership" err + +' + test_expect_success 'cloning locally respects "-u" for fetching refs' ' test_must_fail git clone --bare -u false a should_not_work.git ' diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh index e93e0d0cc3..8a15237736 100755 --- a/t/t5606-clone-options.sh +++ b/t/t5606-clone-options.sh @@ -4,7 +4,6 @@ test_description='basic clone options' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index 7ceaa8194d..82e3621ec5 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -4,7 +4,6 @@ test_description='some bundle related tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -171,6 +170,13 @@ test_expect_success 'clone bundle with different fsckObjects configurations' ' test_must_fail git -c transfer.fsckObjects=true \ clone bundle-fsck/bad.bundle bundle-transfer-fsck 2>err && + test_grep "missingEmail" err && + + git -c fetch.fsckObjects=true -c fetch.fsck.missingEmail=ignore \ + clone bundle-fsck/bad.bundle bundle-fsck-ignore && + + test_must_fail git -c fetch.fsckObjects=true -c fetch.fsck.missingEmail=error \ + clone bundle-fsck/bad.bundle bundle-fsck-error 2>err && test_grep "missingEmail" err ' diff --git a/t/t5609-clone-branch.sh b/t/t5609-clone-branch.sh index 252e1f7c20..f86a674a03 100755 --- a/t/t5609-clone-branch.sh +++ b/t/t5609-clone-branch.sh @@ -4,7 +4,6 @@ test_description='clone --branch option' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_HEAD() { diff --git a/t/t5610-clone-detached.sh b/t/t5610-clone-detached.sh index 022ed3d87c..a7ec21eda5 100755 --- a/t/t5610-clone-detached.sh +++ b/t/t5610-clone-detached.sh @@ -4,7 +4,6 @@ test_description='test cloning a repository with detached HEAD' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh head_is_detached() { diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh index 298d4befab..4873089a8c 100755 --- a/t/t5611-clone-config.sh +++ b/t/t5611-clone-config.sh @@ -4,7 +4,6 @@ test_description='tests for git clone -c key=value' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'clone -c sets config in cloned repo' ' diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh index 72762de977..3126cfd7e9 100755 --- a/t/t5612-clone-refspec.sh +++ b/t/t5612-clone-refspec.sh @@ -4,7 +4,6 @@ test_description='test refspec written by clone-command' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh index 7708cbafa9..c752804a8e 100755 --- a/t/t5613-info-alternate.sh +++ b/t/t5613-info-alternate.sh @@ -5,7 +5,6 @@ test_description='test transitive info/alternate entries' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'preparing first repository' ' diff --git a/t/t5614-clone-submodules-shallow.sh b/t/t5614-clone-submodules-shallow.sh index c2a2bb453e..0c85ef834a 100755 --- a/t/t5614-clone-submodules-shallow.sh +++ b/t/t5614-clone-submodules-shallow.sh @@ -2,7 +2,6 @@ test_description='Test shallow cloning of repos with submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pwd=$(pwd) diff --git a/t/t5615-alternate-env.sh b/t/t5615-alternate-env.sh index 83513e46a3..9d6aa2187f 100755 --- a/t/t5615-alternate-env.sh +++ b/t/t5615-alternate-env.sh @@ -2,7 +2,6 @@ test_description='handling of alternates in environment variables' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_obj () { diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index 2da7291e37..4650451964 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -229,7 +229,7 @@ test_expect_success 'fetch --refetch triggers repacking' ' GIT_TRACE2_EVENT="$PWD/trace1.event" \ git -C pc1 fetch --refetch origin && - test_subcommand git maintenance run --auto --no-quiet <trace1.event && + test_subcommand git maintenance run --auto --no-quiet --detach <trace1.event && grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace1.event && grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace1.event && @@ -238,7 +238,7 @@ test_expect_success 'fetch --refetch triggers repacking' ' -c gc.autoPackLimit=0 \ -c maintenance.incremental-repack.auto=1234 \ -C pc1 fetch --refetch origin && - test_subcommand git maintenance run --auto --no-quiet <trace2.event && + test_subcommand git maintenance run --auto --no-quiet --detach <trace2.event && grep \"param\":\"gc.autopacklimit\",\"value\":\"0\" trace2.event && grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace2.event && @@ -247,7 +247,7 @@ test_expect_success 'fetch --refetch triggers repacking' ' -c gc.autoPackLimit=1234 \ -c maintenance.incremental-repack.auto=0 \ -C pc1 fetch --refetch origin && - test_subcommand git maintenance run --auto --no-quiet <trace3.event && + test_subcommand git maintenance run --auto --no-quiet --detach <trace3.event && grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace3.event && grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"0\" trace3.event ' @@ -693,6 +693,36 @@ test_expect_success 'lazy-fetch in submodule succeeds' ' git -C client restore --recurse-submodules --source=HEAD^ :/ ' +test_expect_success 'after fetching descendants of non-promisor commits, gc works' ' + # Setup + git init full && + git -C full config uploadpack.allowfilter 1 && + git -C full config uploadpack.allowanysha1inwant 1 && + touch full/foo && + git -C full add foo && + git -C full commit -m "commit 1" && + git -C full checkout --detach && + + # Partial clone and push commit to remote + git clone "file://$(pwd)/full" --filter=blob:none partial && + echo "hello" > partial/foo && + git -C partial commit -a -m "commit 2" && + git -C partial push && + + # gc in partial repo + git -C partial gc --prune=now && + + # Create another commit in normal repo + git -C full checkout main && + echo " world" >> full/foo && + git -C full commit -a -m "commit 3" && + + # Pull from remote in partial repo, and run gc again + git -C partial pull && + git -C partial gc --prune=now +' + + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh index 5a4d7936a7..6884338249 100755 --- a/t/t5617-clone-submodules-remote.sh +++ b/t/t5617-clone-submodules-remote.sh @@ -5,7 +5,6 @@ test_description='Test cloning repos with submodules using remote-tracking branc GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pwd=$(pwd) diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh index f905db0a3f..2fb6d549d3 100755 --- a/t/t5618-alternate-refs.sh +++ b/t/t5618-alternate-refs.sh @@ -2,7 +2,6 @@ test_description='test handling of --alternate-refs traversal' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Avoid test_commit because we want a specific and known set of refs: diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index c48830de8f..de904c1655 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -5,7 +5,6 @@ test_description='test protocol v2 server commands' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'test capability advertisement' ' diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 1ef540f73d..d3df81e785 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -185,6 +185,43 @@ test_expect_success 'server-options are sent when using ls-remote' ' grep "server-option=world" log ' +test_expect_success 'server-options from configuration are used by ls-remote' ' + test_when_finished "rm -rf log myclone" && + git clone "file://$(pwd)/file_parent" myclone && + cat >expect <<-EOF && + $(git -C file_parent rev-parse refs/heads/main)$(printf "\t")refs/heads/main + EOF + + # Default server options from configuration are used + git -C myclone config --add remote.origin.serverOption foo && + git -C myclone config --add remote.origin.serverOption bar && + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + ls-remote origin main >actual && + test_cmp expect actual && + test_grep "ls-remote> server-option=foo" log && + test_grep "ls-remote> server-option=bar" log && + rm -f log && + + # Empty value of remote.<name>.serverOption clears the list + git -C myclone config --add remote.origin.serverOption "" && + git -C myclone config --add remote.origin.serverOption tar && + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + ls-remote origin main >actual && + test_cmp expect actual && + test_grep "ls-remote> server-option=tar" log && + test_grep ! "ls-remote> server-option=foo" log && + test_grep ! "ls-remote> server-option=bar" log && + rm -f log && + + # Server option from command line overrides those from configuration + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + ls-remote -o hello -o world origin main >actual && + test_cmp expect actual && + test_grep "ls-remote> server-option=hello" log && + test_grep "ls-remote> server-option=world" log && + test_grep ! "ls-remote> server-option=tar" log +' + test_expect_success 'warn if using server-option with ls-remote with legacy protocol' ' test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \ ls-remote -o hello -o world "file://$(pwd)/file_parent" main 2>err && @@ -381,6 +418,54 @@ test_expect_success 'server-options are sent when fetching' ' grep "server-option=world" log ' +test_expect_success 'server-options are sent when fetch multiple remotes' ' + test_when_finished "rm -f log server_options_sent" && + git clone "file://$(pwd)/file_parent" child_multi_remotes && + git -C child_multi_remotes remote add another "file://$(pwd)/file_parent" && + GIT_TRACE_PACKET="$(pwd)/log" git -C child_multi_remotes -c protocol.version=2 \ + fetch -o hello --all && + grep "fetch> server-option=hello" log >server_options_sent && + test_line_count = 2 server_options_sent +' + +test_expect_success 'server-options from configuration are used by git-fetch' ' + test_when_finished "rm -rf log myclone" && + git clone "file://$(pwd)/file_parent" myclone && + git -C file_parent log -1 --format=%s >expect && + + # Default server options from configuration are used + git -C myclone config --add remote.origin.serverOption foo && + git -C myclone config --add remote.origin.serverOption bar && + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + fetch origin main && + git -C myclone log -1 --format=%s origin/main >actual && + test_cmp expect actual && + test_grep "fetch> server-option=foo" log && + test_grep "fetch> server-option=bar" log && + rm -f log && + + # Empty value of remote.<name>.serverOption clears the list + git -C myclone config --add remote.origin.serverOption "" && + git -C myclone config --add remote.origin.serverOption tar && + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + fetch origin main && + git -C myclone log -1 --format=%s origin/main >actual && + test_cmp expect actual && + test_grep "fetch> server-option=tar" log && + test_grep ! "fetch> server-option=foo" log && + test_grep ! "fetch> server-option=bar" log && + rm -f log && + + # Server option from command line overrides those from configuration + GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \ + fetch -o hello -o world origin main && + git -C myclone log -1 --format=%s origin/main >actual && + test_cmp expect actual && + test_grep "fetch> server-option=hello" log && + test_grep "fetch> server-option=world" log && + test_grep ! "fetch> server-option=tar" log +' + test_expect_success 'warn if using server-option with fetch with legacy protocol' ' test_when_finished "rm -rf temp_child" && @@ -404,6 +489,37 @@ test_expect_success 'server-options are sent when cloning' ' grep "server-option=world" log ' +test_expect_success 'server-options from configuration are used by git-clone' ' + test_when_finished "rm -rf log myclone" && + + # Default server options from configuration are used + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \ + clone "file://$(pwd)/file_parent" myclone && + test_grep "clone> server-option=foo" log && + test_grep "clone> server-option=bar" log && + rm -rf log myclone && + + # Empty value of remote.<name>.serverOption clears the list + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \ + -c remote.origin.serverOption= -c remote.origin.serverOption=tar \ + clone "file://$(pwd)/file_parent" myclone && + test_grep "clone> server-option=tar" log && + test_grep ! "clone> server-option=foo" log && + test_grep ! "clone> server-option=bar" log && + rm -rf log myclone && + + # Server option from command line overrides those from configuration + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + -c remote.origin.serverOption=tar \ + clone --server-option=hello --server-option=world \ + "file://$(pwd)/file_parent" myclone && + test_grep "clone> server-option=hello" log && + test_grep "clone> server-option=world" log && + test_grep ! "clone> server-option=tar" log +' + test_expect_success 'warn if using server-option with clone with legacy protocol' ' test_when_finished "rm -rf myclone" && @@ -415,6 +531,23 @@ test_expect_success 'warn if using server-option with clone with legacy protocol test_grep "server options require protocol version 2 or later" err ' +test_expect_success 'server-option configuration with legacy protocol is ok' ' + test_when_finished "rm -rf myclone" && + + env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \ + -c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \ + clone "file://$(pwd)/file_parent" myclone +' + +test_expect_success 'invalid server-option configuration' ' + test_when_finished "rm -rf myclone" && + + test_must_fail git -c protocol.version=2 \ + -c remote.origin.serverOption \ + clone "file://$(pwd)/file_parent" myclone 2>err && + test_grep "error: missing value for '\''remote.origin.serveroption'\''" err +' + test_expect_success 'upload-pack respects config using protocol v2' ' git init server && write_script server/.git/hook <<-\EOF && diff --git a/t/t5704-protocol-violations.sh b/t/t5704-protocol-violations.sh index 11be64fc03..2b33fced23 100755 --- a/t/t5704-protocol-violations.sh +++ b/t/t5704-protocol-violations.sh @@ -5,7 +5,6 @@ of these cases it will generally be acceptable for one side to break off communications if the other side says something unexpected. We are mostly making sure that we do not segfault or otherwise behave badly.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'extra delim packet in v2 ls-refs args' ' diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh index b8a722ec27..ed38c76c29 100755 --- a/t/t5705-session-id-in-capabilities.sh +++ b/t/t5705-session-id-in-capabilities.sh @@ -2,7 +2,6 @@ test_description='session ID in capabilities' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh REPO="$(pwd)/repo" diff --git a/t/t5750-bundle-uri-parse.sh b/t/t5750-bundle-uri-parse.sh index 81bdf58b94..80a3f83ffb 100755 --- a/t/t5750-bundle-uri-parse.sh +++ b/t/t5750-bundle-uri-parse.sh @@ -3,7 +3,6 @@ test_description="Test bundle-uri bundle_uri_parse_line()" TEST_NO_CREATE_REPO=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'bundle_uri_parse_line() just URIs' ' diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 20f43f7b7d..d21877150e 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -344,4 +344,15 @@ test_expect_success 'fetch tag' ' compare_refs local v1.0 server v1.0 ' +test_expect_success 'totally broken helper reports failure message' ' + write_script git-remote-broken <<-\EOF && + read cap_cmd + exit 1 + EOF + test_must_fail \ + env PATH="$PWD:$PATH" \ + git clone broken://example.com/foo.git 2>stderr && + grep aborted stderr +' + test_done diff --git a/t/t5802-connect-helper.sh b/t/t5802-connect-helper.sh index c6c2661878..a7be375bce 100755 --- a/t/t5802-connect-helper.sh +++ b/t/t5802-connect-helper.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='ext::cmd remote "connect" helper' + . ./test-lib.sh test_expect_success setup ' diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh index 862610256f..96a2c46e7a 100755 --- a/t/t5810-proto-disable-local.sh +++ b/t/t5810-proto-disable-local.sh @@ -2,7 +2,6 @@ test_description='test disabling of local paths in clone/fetch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" diff --git a/t/t5811-proto-disable-git.sh b/t/t5811-proto-disable-git.sh index ed773e7432..b0061e6a37 100755 --- a/t/t5811-proto-disable-git.sh +++ b/t/t5811-proto-disable-git.sh @@ -2,7 +2,6 @@ test_description='test disabling of git-over-tcp in clone/fetch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" . "$TEST_DIRECTORY/lib-git-daemon.sh" diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index 769c717e88..96187efaa8 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test disabling of git-over-http in clone/fetch' + . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" . "$TEST_DIRECTORY/lib-httpd.sh" diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh index 2e975dc70e..045e2fe6ce 100755 --- a/t/t5813-proto-disable-ssh.sh +++ b/t/t5813-proto-disable-ssh.sh @@ -2,7 +2,6 @@ test_description='test disabling of git-over-ssh in clone/fetch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" diff --git a/t/t5814-proto-disable-ext.sh b/t/t5814-proto-disable-ext.sh index 9d6f7dfa2c..9587a842bc 100755 --- a/t/t5814-proto-disable-ext.sh +++ b/t/t5814-proto-disable-ext.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test disabling of remote-helper paths in clone/fetch' + . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh index 4d5956cc18..081a07cbae 100755 --- a/t/t5815-submodule-protos.sh +++ b/t/t5815-submodule-protos.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test protocol filtering with submodules' + . ./test-lib.sh . "$TEST_DIRECTORY"/lib-proto-disable.sh diff --git a/t/t5900-repo-selection.sh b/t/t5900-repo-selection.sh index a84faac242..923fc90f87 100755 --- a/t/t5900-repo-selection.sh +++ b/t/t5900-repo-selection.sh @@ -2,7 +2,6 @@ test_description='selecting remote repo in ambiguous cases' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh reset() { diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index f6d17ee902..6289a2e8b0 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -5,7 +5,6 @@ test_description='miscellaneous rev-list tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh index 3553bbbfe7..73a2465aa0 100755 --- a/t/t6001-rev-list-graft.sh +++ b/t/t6001-rev-list-graft.sh @@ -5,7 +5,6 @@ test_description='Revision traversal vs grafts and path limiter' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index 162cf50778..daa009c9a1 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -4,7 +4,6 @@ # test_description='Tests git rev-list --bisect functionality' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions @@ -309,4 +308,9 @@ test_expect_success '--bisect-all --first-parent' ' test_cmp expect actual ' +test_expect_success '--bisect without any revisions' ' + git rev-list --bisect HEAD..HEAD >out && + test_must_be_empty out +' + test_done diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh index 5cf2cee74d..0d7055d46d 100755 --- a/t/t6003-rev-list-topo-order.sh +++ b/t/t6003-rev-list-topo-order.sh @@ -5,7 +5,6 @@ test_description='Tests git rev-list --topo-order functionality' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions diff --git a/t/t6005-rev-list-count.sh b/t/t6005-rev-list-count.sh index ee0306aeec..6cde997e13 100755 --- a/t/t6005-rev-list-count.sh +++ b/t/t6005-rev-list-count.sh @@ -2,7 +2,6 @@ test_description='git rev-list --max-count and --skip test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index f1623b1c06..eb93d68d7d 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -8,26 +8,45 @@ test_description='git rev-list --pretty=format test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh test_tick -# Tested non-UTF-8 encoding -test_encoding="ISO8859-1" - -# String "added" in German -# (translated with Google Translate), -# encoded in UTF-8, used as a commit log message below. -added_utf8_part=$(printf "\303\274") -added_utf8_part_iso88591=$(echo "$added_utf8_part" | iconv -f utf-8 -t $test_encoding) -added=$(printf "added (hinzugef${added_utf8_part}gt) foo") -added_iso88591=$(echo "$added" | iconv -f utf-8 -t $test_encoding) -# same but "changed" -changed_utf8_part=$(printf "\303\244") -changed_utf8_part_iso88591=$(echo "$changed_utf8_part" | iconv -f utf-8 -t $test_encoding) -changed=$(printf "changed (ge${changed_utf8_part}ndert) foo") -changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t $test_encoding) + +if test_have_prereq ICONV +then + # Tested non-UTF-8 encoding + test_encoding="ISO8859-1" + + # String "added" in German + # (translated with Google Translate), + # encoded in UTF-8, used as a commit log message below. + added_utf8_part=$(printf "\303\274") + added_utf8_part_iso88591=$(echo "$added_utf8_part" | iconv -f utf-8 -t $test_encoding) + added=$(printf "added (hinzugef${added_utf8_part}gt) foo") + added_iso88591=$(echo "$added" | iconv -f utf-8 -t $test_encoding) + # same but "changed" + changed_utf8_part=$(printf "\303\244") + changed_utf8_part_iso88591=$(echo "$changed_utf8_part" | iconv -f utf-8 -t $test_encoding) + changed=$(printf "changed (ge${changed_utf8_part}ndert) foo") + changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t $test_encoding) +else + # Tested non-UTF-8 encoding + test_encoding="UTF-8" + + # String "added" in German + # (translated with Google Translate), + # encoded in UTF-8, used as a commit log message below. + added_utf8_part="u" + added_utf8_part_iso88591="u" + added=$(printf "added (hinzugef${added_utf8_part}gt) foo") + added_iso88591="$added" + # same but "changed" + changed_utf8_part="a" + changed_utf8_part_iso88591="a" + changed=$(printf "changed (ge${changed_utf8_part}ndert) foo") + changed_iso88591="$changed" +fi # Count of char to truncate # Number is chosen so, that non-ACSII characters @@ -55,7 +74,7 @@ test_expect_success 'setup' ' git config --unset i18n.commitEncoding ' -# usage: test_format [argument...] name format_string [failure] <expected_output +# usage: test_format [argument...] name format_string [success|failure] [prereq] <expected_output test_format () { local args= while true @@ -69,7 +88,7 @@ test_format () { esac done cat >expect.$1 - test_expect_${3:-success} "format $1" " + test_expect_${3:-success} $4 "format $1" " git rev-list $args --pretty=format:'$2' main >output.$1 && test_cmp expect.$1 output.$1 " @@ -198,7 +217,7 @@ Thu, 7 Apr 2005 15:13:13 -0700 1112911993 EOF -test_format encoding %e <<EOF +test_format encoding %e success ICONV <<EOF commit $head2 $test_encoding commit $head1 @@ -374,7 +393,7 @@ test_expect_success 'setup complex body' ' head3_short=$(git rev-parse --short $head3) ' -test_format complex-encoding %e <<EOF +test_format complex-encoding %e success ICONV <<EOF commit $head3 $test_encoding commit $head2 diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index 2d337d7287..6f3e543977 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -5,7 +5,6 @@ test_description='test git rev-list --cherry-pick -- file' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # A---B---D---F diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh index 2cdef6fdf9..a0a070b404 100755 --- a/t/t6008-rev-list-submodule.sh +++ b/t/t6008-rev-list-submodule.sh @@ -8,7 +8,6 @@ test_description='git rev-list involving submodules that this repo has' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh index 91db8fafe8..9c9a8459af 100755 --- a/t/t6009-rev-list-parent.sh +++ b/t/t6009-rev-list-parent.sh @@ -5,7 +5,6 @@ test_description='ancestor culling and limiting by parent number' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_revlist () { diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh index f96ea82e78..44c726ea39 100755 --- a/t/t6010-merge-base.sh +++ b/t/t6010-merge-base.sh @@ -6,7 +6,6 @@ test_description='Merge base and parent list computation. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh M=1130000000 diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh index b2e422cf0f..bad02cf5b8 100755 --- a/t/t6011-rev-list-with-bad-commit.sh +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -2,7 +2,6 @@ test_description='git rev-list should notice bad commits' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Note: diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh index 4128269c1d..39793cbbd6 100755 --- a/t/t6013-rev-list-reverse-parents.sh +++ b/t/t6013-rev-list-reverse-parents.sh @@ -5,7 +5,6 @@ test_description='--reverse combines with --parents' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh index 16b8bd1d09..c9bedd29cb 100755 --- a/t/t6014-rev-list-all.sh +++ b/t/t6014-rev-list-all.sh @@ -2,7 +2,6 @@ test_description='--all includes detached HEADs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh index a0a40fe55c..4821b90e74 100755 --- a/t/t6017-rev-list-stdin.sh +++ b/t/t6017-rev-list-stdin.sh @@ -8,7 +8,6 @@ test_description='log family learns --stdin' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check () { diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index 3b181f771c..bb55c7e3c3 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -5,7 +5,6 @@ test_description='rev-list/rev-parse --glob' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh commit () { diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index fe75a06572..5d444bfe20 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -8,7 +8,6 @@ test_description='Test git-bundle' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bundle.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -652,4 +651,36 @@ test_expect_success 'send a bundle to standard output' ' test_cmp expect actual ' +test_expect_success 'unbundle outside of a repository' ' + git bundle create some.bundle HEAD && + echo "fatal: Need a repository to unbundle." >expect && + nongit test_must_fail git bundle unbundle "$(pwd)/some.bundle" 2>err && + test_cmp expect err +' + +test_expect_success 'list-heads outside of a repository' ' + git bundle create some.bundle HEAD && + cat >expect <<-EOF && + $(git rev-parse HEAD) HEAD + EOF + nongit git bundle list-heads "$(pwd)/some.bundle" >actual && + test_cmp expect actual +' + +for hash in sha1 sha256 +do + test_expect_success "list-heads with bundle using $hash" ' + test_when_finished "rm -rf hash" && + git init --object-format=$hash hash && + test_commit -C hash initial && + git -C hash bundle create hash.bundle HEAD && + + cat >expect <<-EOF && + $(git -C hash rev-parse HEAD) HEAD + EOF + git bundle list-heads hash/hash.bundle >actual && + test_cmp expect actual + ' +done + test_done diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh index 51df02105d..5fe942a293 100755 --- a/t/t6021-rev-list-exclude-hidden.sh +++ b/t/t6021-rev-list-exclude-hidden.sh @@ -2,7 +2,6 @@ test_description='git rev-list --exclude-hidden test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh index 127180e1c9..7553a9cca2 100755 --- a/t/t6022-rev-list-missing.sh +++ b/t/t6022-rev-list-missing.sh @@ -2,7 +2,6 @@ test_description='handling of missing objects in rev-list' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We setup the repository with two commits, this way HEAD is always diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index acc281c116..0b719bbae6 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -5,7 +5,6 @@ test_description='remote tracking stats' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh advance () { diff --git a/t/t6041-bisect-submodule.sh b/t/t6041-bisect-submodule.sh index 3946e18089..82013fc903 100755 --- a/t/t6041-bisect-submodule.sh +++ b/t/t6041-bisect-submodule.sh @@ -2,7 +2,6 @@ test_description='bisect can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index c6e9b33e44..aa1b535187 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -97,30 +97,42 @@ test_expect_success 'set up buggy branch' ' ' test_expect_success 'replace the author' ' - git cat-file commit $HASH2 | grep "author A U Thor" && - R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && - git cat-file commit $R | grep "author O Thor" && + git cat-file commit $HASH2 >actual && + test_grep "author A U Thor" actual && + R=$(sed -e "s/A U/O/" actual | git hash-object -t commit --stdin -w) && + git cat-file commit $R >actual && + test_grep "author O Thor" actual && git update-ref refs/replace/$HASH2 $R && - git show HEAD~5 | grep "O Thor" && - git show $HASH2 | grep "O Thor" + git show HEAD~5 >actual && + test_grep "O Thor" actual && + git show $HASH2 >actual && + test_grep "O Thor" actual ' test_expect_success 'test --no-replace-objects option' ' - git cat-file commit $HASH2 | grep "author O Thor" && - git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" && - git show $HASH2 | grep "O Thor" && - git --no-replace-objects show $HASH2 | grep "A U Thor" + git cat-file commit $HASH2 >actual && + test_grep "author O Thor" actual && + git --no-replace-objects cat-file commit $HASH2 >actual && + test_grep "author A U Thor" actual && + git show $HASH2 >actual && + test_grep "O Thor" actual && + git --no-replace-objects show $HASH2 >actual && + test_grep "A U Thor" actual ' test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' ' - GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" && - GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor" + GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 >actual && + test_grep "author A U Thor" actual && + GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 >actual && + test_grep "A U Thor" actual ' test_expect_success 'test core.usereplacerefs config option' ' test_config core.usereplacerefs false && - git cat-file commit $HASH2 | grep "author A U Thor" && - git show $HASH2 | grep "A U Thor" + git cat-file commit $HASH2 >actual && + test_grep "author A U Thor" actual && + git show $HASH2 >actual && + test_grep "A U Thor" actual ' cat >tag.sig <<EOF @@ -147,14 +159,18 @@ test_expect_success 'repack, clone and fetch work' ' git clone --no-hardlinks . clone_dir && ( cd clone_dir && - git show HEAD~5 | grep "A U Thor" && - git show $HASH2 | grep "A U Thor" && + git show HEAD~5 >actual && + test_grep "A U Thor" actual && + git show $HASH2 >actual && + test_grep "A U Thor" actual && git cat-file commit $R && git repack -a -d && test_must_fail git cat-file commit $R && git fetch ../ "refs/replace/*:refs/replace/*" && - git show HEAD~5 | grep "O Thor" && - git show $HASH2 | grep "O Thor" && + git show HEAD~5 >actual && + test_grep "O Thor" actual && + git show $HASH2 >actual && + test_grep "O Thor" actual && git cat-file commit $R ) ' @@ -168,13 +184,15 @@ test_expect_success '"git replace" listing and deleting' ' test_must_fail git replace --delete && test_must_fail git replace -l -d $HASH2 && git replace -d $HASH2 && - git show $HASH2 | grep "A U Thor" && + git show $HASH2 >actual && + test_grep "A U Thor" actual && test -z "$(git replace -l)" ' test_expect_success '"git replace" replacing' ' git replace $HASH2 $R && - git show $HASH2 | grep "O Thor" && + git show $HASH2 >actual && + test_grep "O Thor" actual && test_must_fail git replace $HASH2 $R && git replace -f $HASH2 $R && test_must_fail git replace -f && @@ -185,7 +203,8 @@ test_expect_success '"git replace" resolves sha1' ' SHORTHASH2=$(git rev-parse --short=8 $HASH2) && git replace -d $SHORTHASH2 && git replace $SHORTHASH2 $R && - git show $HASH2 | grep "O Thor" && + git show $HASH2 >actual && + test_grep "O Thor" actual && test_must_fail git replace $HASH2 $R && git replace -f $HASH2 $R && test_must_fail git replace --force && @@ -208,10 +227,12 @@ test_expect_success '"git replace" resolves sha1' ' # test_expect_success 'create parallel branch without the bug' ' git replace -d $HASH2 && - git show $HASH2 | grep "A U Thor" && + git show $HASH2 >actual && + test_grep "A U Thor" actual && git checkout $HASH1 && git cherry-pick $HASH2 && - git show $HASH5 | git apply && + git show $HASH5 >actual && + git apply actual && git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello && PARA2=$(git rev-parse --verify HEAD) && git cherry-pick $HASH3 && @@ -224,7 +245,8 @@ test_expect_success 'create parallel branch without the bug' ' git checkout main && cur=$(git rev-parse --verify HEAD) && test "$cur" = "$HASH7" && - git log --pretty=oneline | grep $PARA2 && + git log --pretty=oneline >actual && + test_grep $PARA2 actual && git remote add cloned ./clone_dir ' @@ -233,23 +255,30 @@ test_expect_success 'push to cloned repo' ' ( cd clone_dir && git checkout parallel && - git log --pretty=oneline | grep $PARA2 + git log --pretty=oneline >actual && + test_grep $PARA2 actual ) ' test_expect_success 'push branch with replacement' ' - git cat-file commit $PARA3 | grep "author A U Thor" && - S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && - git cat-file commit $S | grep "author O Thor" && + git cat-file commit $PARA3 >actual && + test_grep "author A U Thor" actual && + S=$(sed -e "s/A U/O/" actual | git hash-object -t commit --stdin -w) && + git cat-file commit $S >actual && + test_grep "author O Thor" actual && git replace $PARA3 $S && - git show $HASH6~2 | grep "O Thor" && - git show $PARA3 | grep "O Thor" && + git show $HASH6~2 >actual && + test_grep "O Thor" actual && + git show $PARA3 >actual && + test_grep "O Thor" actual && git push cloned $HASH6^:refs/heads/parallel2 && ( cd clone_dir && git checkout parallel2 && - git log --pretty=oneline | grep $PARA3 && - git show $PARA3 | grep "A U Thor" + git log --pretty=oneline >actual && + test_grep $PARA3 actual && + git show $PARA3 >actual && + test_grep "A U Thor" actual ) ' @@ -259,14 +288,14 @@ test_expect_success 'fetch branch with replacement' ' cd clone_dir && git fetch origin refs/heads/tofetch:refs/heads/parallel3 && git log --pretty=oneline parallel3 >output.txt && - ! grep $PARA3 output.txt && + test_grep ! $PARA3 output.txt && git show $PARA3 >para3.txt && - grep "A U Thor" para3.txt && + test_grep "A U Thor" para3.txt && git fetch origin "refs/replace/*:refs/replace/*" && git log --pretty=oneline parallel3 >output.txt && - grep $PARA3 output.txt && + test_grep $PARA3 output.txt && git show $PARA3 >para3.txt && - grep "O Thor" para3.txt + test_grep "O Thor" para3.txt ) ' @@ -283,8 +312,8 @@ test_expect_success 'bisect and replacements' ' ' test_expect_success 'index-pack and replacements' ' - git --no-replace-objects rev-list --objects HEAD | - git --no-replace-objects pack-objects test- && + git --no-replace-objects rev-list --objects HEAD >actual && + git --no-replace-objects pack-objects test- <actual && git index-pack test-*.pack ' @@ -318,7 +347,8 @@ test_expect_success '-f option bypasses the type check' ' ' test_expect_success 'git cat-file --batch works on replace objects' ' - git replace | grep $PARA3 && + git replace >actual && + test_grep $PARA3 actual && echo $PARA3 | git cat-file --batch ' @@ -343,7 +373,8 @@ test_expect_success 'test --format medium' ' echo "$PARA3 -> $S" && echo "$MYTAG -> $HASH1" } | sort >expected && - git replace -l --format medium | sort >actual && + git replace -l --format medium >output && + sort output >actual && test_cmp expected actual ' @@ -355,7 +386,8 @@ test_expect_success 'test --format long' ' echo "$PARA3 (commit) -> $S (commit)" && echo "$MYTAG (tag) -> $HASH1 (commit)" } | sort >expected && - git replace --format=long | sort >actual && + git replace --format=long >output && + sort output >actual && test_cmp expected actual ' @@ -373,12 +405,16 @@ test_expect_success 'setup fake editors' ' test_expect_success '--edit with and without already replaced object' ' test_must_fail env GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" && GIT_EDITOR=./fakeeditor git replace --force --edit "$PARA3" && - git replace -l | grep "$PARA3" && - git cat-file commit "$PARA3" | grep "A fake Thor" && + git replace -l >actual && + test_grep "$PARA3" actual && + git cat-file commit "$PARA3" >actual && + test_grep "A fake Thor" actual && git replace -d "$PARA3" && GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" && - git replace -l | grep "$PARA3" && - git cat-file commit "$PARA3" | grep "A fake Thor" + git replace -l >actual && + test_grep "$PARA3" actual && + git cat-file commit "$PARA3" >actual && + test_grep "A fake Thor" actual ' test_expect_success '--edit and change nothing or command failed' ' @@ -386,8 +422,10 @@ test_expect_success '--edit and change nothing or command failed' ' test_must_fail env GIT_EDITOR=true git replace --edit "$PARA3" && test_must_fail env GIT_EDITOR="./failingfakeeditor" git replace --edit "$PARA3" && GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" && - git replace -l | grep "$PARA3" && - git cat-file commit "$PARA3" | grep "A fake Thor" + git replace -l >actual && + test_grep "$PARA3" actual && + git cat-file commit "$PARA3" >actual && + test_grep "A fake Thor" actual ' test_expect_success 'replace ref cleanup' ' @@ -467,7 +505,8 @@ test_expect_success GPG 'set up a merge commit with a mergetag' ' git checkout main && git merge -s ours test_tag && HASH10=$(git rev-parse --verify HEAD) && - git cat-file commit $HASH10 | grep "^mergetag object" + git cat-file commit $HASH10 >actual && + test_grep "^mergetag object" actual ' test_expect_success GPG '--graft on a commit with a mergetag' ' diff --git a/t/t6060-merge-index.sh b/t/t6060-merge-index.sh index 1a8b64cce1..e6b3e6ec77 100755 --- a/t/t6060-merge-index.sh +++ b/t/t6060-merge-index.sh @@ -2,7 +2,6 @@ test_description='basic git merge-index / git-merge-one-file tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup diverging branches' ' diff --git a/t/t6100-rev-list-in-order.sh b/t/t6100-rev-list-in-order.sh index 88ed7bd75a..e934bc239c 100755 --- a/t/t6100-rev-list-in-order.sh +++ b/t/t6100-rev-list-in-order.sh @@ -2,7 +2,6 @@ test_description='rev-list testing in-commit-order' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup a commit history with trees, blobs' ' diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index d20723d627..5f55ab98d3 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -8,7 +8,6 @@ test_description='Test git rev-parse with different parent options' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 5d28507efc..22dfd6d978 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -2,7 +2,6 @@ test_description='git rev-list should handle unexpected object types' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup well-formed objects' ' diff --git a/t/t6110-rev-list-sparse.sh b/t/t6110-rev-list-sparse.sh index ddefc7f24e..13c1da5352 100755 --- a/t/t6110-rev-list-sparse.sh +++ b/t/t6110-rev-list-sparse.sh @@ -4,7 +4,6 @@ test_description='operations that cull histories in unusual ways' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6113-rev-list-bitmap-filters.sh b/t/t6113-rev-list-bitmap-filters.sh index a9656a1ec8..902854cbfa 100755 --- a/t/t6113-rev-list-bitmap-filters.sh +++ b/t/t6113-rev-list-bitmap-filters.sh @@ -2,7 +2,6 @@ test_description='rev-list combining bitmaps and filters' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bitmap.sh diff --git a/t/t6114-keep-packs.sh b/t/t6114-keep-packs.sh index 44246f8a63..a584522ef2 100755 --- a/t/t6114-keep-packs.sh +++ b/t/t6114-keep-packs.sh @@ -2,7 +2,6 @@ test_description='rev-list with .keep packs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6115-rev-list-du.sh b/t/t6115-rev-list-du.sh index 21c4a211b1..3385fe9f13 100755 --- a/t/t6115-rev-list-du.sh +++ b/t/t6115-rev-list-du.sh @@ -2,7 +2,6 @@ test_description='basic tests of rev-list --disk-usage' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # we want a mix of reachable and unreachable, as well as diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 05ed2510d9..3f6160d702 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -14,11 +14,11 @@ test_description='test describe' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_describe () { indir= && + outcome=success && while test $# != 0 do case "$1" in @@ -26,6 +26,9 @@ check_describe () { indir="$2" shift ;; + --expect-failure) + outcome=failure + ;; *) break ;; @@ -36,7 +39,7 @@ check_describe () { expect="$1" shift describe_opts="$@" - test_expect_success "describe $describe_opts" ' + test_expect_${outcome} "describe $describe_opts" ' git ${indir:+ -C "$indir"} describe $describe_opts >raw && sed -e "s/-g[0-9a-f]*\$/-gHASH/" <raw >actual && echo "$expect" >expect && @@ -617,7 +620,7 @@ test_expect_success 'name-rev --annotate-stdin works with commitGraph' ' # B # o -# \ +# H \ # o-----o---o----x # A # @@ -627,6 +630,7 @@ test_expect_success 'setup: describe commits with disjoint bases' ' cd disjoint1 && echo o >> file && git add file && git commit -m o && + git tag H -a -m H && echo A >> file && git add file && git commit -m A && git tag A -a -m A && echo o >> file && git add file && git commit -m o && @@ -639,8 +643,9 @@ test_expect_success 'setup: describe commits with disjoint bases' ' ' check_describe -C disjoint1 "A-3-gHASH" HEAD +check_describe -C disjoint1 --expect-failure "A-3-gHASH" --candidates=2 HEAD -# B +# H B # o---o---o------------. # \ # o---o---x @@ -658,6 +663,7 @@ test_expect_success 'setup: describe commits with disjoint bases 2' ' git checkout --orphan branch && echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:00" git commit -m o && echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:01" git commit -m o && + git tag H -a -m H && echo B >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:02" git commit -m B && git tag B -a -m B && git merge --no-ff --allow-unrelated-histories main -m x @@ -665,6 +671,7 @@ test_expect_success 'setup: describe commits with disjoint bases 2' ' ' check_describe -C disjoint2 "B-3-gHASH" HEAD +check_describe -C disjoint2 --expect-failure "B-3-gHASH" --candidates=2 HEAD test_expect_success 'setup misleading taggerdates' ' GIT_COMMITTER_DATE="2006-12-12 12:31" git tag -a -m "another tag" newer-tag-older-commit unique-file~1 @@ -708,4 +715,14 @@ test_expect_success 'describe --broken --dirty with a file with changed stat' ' ) ' +test_expect_success '--always with no refs falls back to commit hash' ' + git rev-parse HEAD >expect && + git describe --no-abbrev --always --match=no-such-tag >actual && + test_cmp expect actual +' + +test_expect_success '--exact-match does not show --always fallback' ' + test_must_fail git describe --exact-match --always +' + test_done diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh index 82de25d549..a7f2603cb4 100755 --- a/t/t6130-pathspec-noglob.sh +++ b/t/t6130-pathspec-noglob.sh @@ -2,7 +2,6 @@ test_description='test globbing (and noglob) of pathspec limiting' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create commits with glob characters' ' diff --git a/t/t6131-pathspec-icase.sh b/t/t6131-pathspec-icase.sh index 770cce026c..e64d938083 100755 --- a/t/t6131-pathspec-icase.sh +++ b/t/t6131-pathspec-icase.sh @@ -2,7 +2,6 @@ test_description='test case insensitive pathspec limiting' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if test_have_prereq CASE_INSENSITIVE_FS diff --git a/t/t6133-pathspec-rev-dwim.sh b/t/t6133-pathspec-rev-dwim.sh index 6dd4bbbf9f..0f722fb340 100755 --- a/t/t6133-pathspec-rev-dwim.sh +++ b/t/t6133-pathspec-rev-dwim.sh @@ -2,7 +2,6 @@ test_description='test dwim of revs versus pathspecs in revision parser' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh index 16ce4cfcc6..9b62a0a65f 100755 --- a/t/t6134-pathspec-in-submodule.sh +++ b/t/t6134-pathspec-in-submodule.sh @@ -2,7 +2,6 @@ test_description='test case exclude pathspec' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup a submodule' ' diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh index 120dcd74a5..67d8c72147 100755 --- a/t/t6135-pathspec-with-attrs.sh +++ b/t/t6135-pathspec-with-attrs.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test labels in pathspecs' + . ./test-lib.sh test_expect_success 'setup a tree' ' diff --git a/t/t6136-pathspec-in-bare.sh b/t/t6136-pathspec-in-bare.sh index 2db37a6596..1284fe0143 100755 --- a/t/t6136-pathspec-in-bare.sh +++ b/t/t6136-pathspec-in-bare.sh @@ -2,7 +2,6 @@ test_description='diagnosing out-of-scope pathspec' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup a bare and non-bare repository' ' diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 5a221f8ef1..011e5df1e6 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -607,34 +607,34 @@ test_expect_success 'merge-msg with "merging" an annotated tag' ' git checkout main^0 && git commit --allow-empty -m "One step ahead" && - git tag -a -m "An annotated one" annote HEAD && + git tag -a -m "An annotated one" annotate HEAD && git checkout main && - git fetch . annote && + git fetch . annotate && git fmt-merge-msg <.git/FETCH_HEAD >actual && { cat <<-\EOF - Merge tag '\''annote'\'' + Merge tag '\''annotate'\'' An annotated one - * tag '\''annote'\'': + * tag '\''annotate'\'': One step ahead EOF } >expected && test_cmp expected actual && test_when_finished "git reset --hard" && - annote=$(git rev-parse annote) && - git merge --no-commit --no-ff $annote && + annotate=$(git rev-parse annotate) && + git merge --no-commit --no-ff $annotate && { cat <<-EOF - Merge tag '\''$annote'\'' + Merge tag '\''$annotate'\'' An annotated one - * tag '\''$annote'\'': + * tag '\''$annotate'\'': One step ahead EOF } >expected && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index eb6c8204e8..a5c7794385 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -769,7 +769,7 @@ test_expect_success 'describe:abbrev=... vs describe --abbrev=...' ' refs/heads/master >actual && test_cmp expect actual && - # Make sure the hash used is atleast 14 digits long + # Make sure the hash used is at least 14 digits long sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart && test 15 -le $(wc -c <hexpart) && @@ -1560,6 +1560,25 @@ test_trailer_option '%(trailers:separator,key_value_separator) changes both sepa Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com> EOF +test_expect_success 'multiple %(trailers) use their own options' ' + git tag -F - tag-with-trailers <<-\EOF && + body + + one: foo + one: bar + two: baz + two: qux + EOF + t1="%(trailers:key=one,key_value_separator=W,separator=X)" && + t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" && + git for-each-ref --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual && + cat >expect <<-\EOF && + oneWfooXoneWbar + twoYbazZtwoYqux + EOF + test_cmp expect actual +' + test_failing_trailer_option () { title=$1 option=$2 cat >expect @@ -1835,6 +1854,24 @@ sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)" sig_crlf=${sig_crlf%dummy} test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf" +test_expect_success 'set up tag with signature and trailers' ' + git tag -F - fake-sig-trailer <<-\EOF + this is the subject + + this is the body + + My-Trailer: foo + -----BEGIN PGP SIGNATURE----- + + not a real signature, but we just care about the + subject/body/trailer parsing. + -----END PGP SIGNATURE----- + EOF +' + +# use "separator=" here to suppress the terminating newline +test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo' + test_expect_success 'git for-each-ref --stdin: empty' ' >in && git for-each-ref --format="%(refname)" --stdin <in >actual && @@ -1907,6 +1944,15 @@ test_expect_success 'git for-each-ref with nested tags' ' test_cmp expect actual ' +test_expect_success 'is-base atom with non-commits' ' + git for-each-ref --format="%(is-base:HEAD) %(refname)" >out 2>err && + grep "(HEAD) refs/heads/main" out && + + test_line_count = 2 err && + grep "error: object .* is a commit, not a blob" err && + grep "error: bad tag pointer to" err +' + GRADE_FORMAT="%(signature:grade)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)" TRUSTLEVEL_FORMAT="%(signature:trustlevel)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)" @@ -1994,8 +2040,7 @@ test_expect_success GPG 'show good signature with custom format' ' --format="$GRADE_FORMAT" >actual && test_cmp expect actual ' -test_expect_success GPGSSH 'show good signature with custom format - with ssh' ' +test_expect_success GPGSSH 'show good signature with custom format with ssh' ' test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" && FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") && cat >expect.tmpl <<-\EOF && diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh index 83b8a19d94..e06feb06e9 100755 --- a/t/t6301-for-each-ref-errors.sh +++ b/t/t6301-for-each-ref-errors.sh @@ -2,7 +2,6 @@ test_description='for-each-ref errors for broken refs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh ZEROS=$ZERO_OID diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index 163c378cfd..bb02b86c16 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -13,7 +13,7 @@ test_expect_success 'setup some history and refs' ' git checkout -b side && test_commit four && git tag -m "An annotated tag" annotated-tag && - git tag -m "Annonated doubly" doubly-annotated-tag annotated-tag && + git tag -m "Annotated doubly" doubly-annotated-tag annotated-tag && # Note that these "signed" tags might not actually be signed. # Tests which care about the distinction should be marked @@ -342,7 +342,7 @@ test_expect_success 'check `%(contents:lines=1)`' ' side |four odd/spot |three annotated-tag |An annotated tag - doubly-annotated-tag |Annonated doubly + doubly-annotated-tag |Annotated doubly doubly-signed-tag |Signed doubly four |four one |one @@ -378,7 +378,7 @@ test_expect_success 'check `%(contents:lines=99999)`' ' side |four odd/spot |three annotated-tag |An annotated tag - doubly-annotated-tag |Annonated doubly + doubly-annotated-tag |Annotated doubly doubly-signed-tag |Signed doubly four |four one |one diff --git a/t/t6400-merge-df.sh b/t/t6400-merge-df.sh index 27d6efdc9a..3de4ef6bd9 100755 --- a/t/t6400-merge-df.sh +++ b/t/t6400-merge-df.sh @@ -7,7 +7,6 @@ test_description='Test merge with directory/file conflicts' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'prepare repository' ' diff --git a/t/t6401-merge-criss-cross.sh b/t/t6401-merge-criss-cross.sh index 1962310408..c8e5ff28e8 100755 --- a/t/t6401-merge-criss-cross.sh +++ b/t/t6401-merge-criss-cross.sh @@ -9,7 +9,6 @@ test_description='Test criss-cross merge' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'prepare repository' ' diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh index 729aac9842..2738b50c2a 100755 --- a/t/t6402-merge-rename.sh +++ b/t/t6402-merge-rename.sh @@ -4,7 +4,6 @@ test_description='Merge-recursive merging renames' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh modify () { diff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh index fb872c5a11..06ab4d7aed 100755 --- a/t/t6403-merge-file.sh +++ b/t/t6403-merge-file.sh @@ -2,7 +2,6 @@ test_description='RCS merge replacement: merge-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6404-recursive-merge.sh b/t/t6404-recursive-merge.sh index 36215518b6..ae687f2ce5 100755 --- a/t/t6404-recursive-merge.sh +++ b/t/t6404-recursive-merge.sh @@ -4,7 +4,6 @@ test_description='Test merge without common ancestors' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # This scenario is based on a real-world repository of Shawn Pearce. @@ -88,7 +87,7 @@ test_expect_success 'result contains a conflict' ' ' test_expect_success 'virtual trees were processed' ' - # TODO: fragile test, relies on ambigious merge-base resolution + # TODO: fragile test, relies on ambiguous merge-base resolution git ls-files --stage >out && cat >expect <<-EOF && diff --git a/t/t6405-merge-symlinks.sh b/t/t6405-merge-symlinks.sh index 29e2b25ce5..7435fce71e 100755 --- a/t/t6405-merge-symlinks.sh +++ b/t/t6405-merge-symlinks.sh @@ -11,7 +11,6 @@ if core.symlinks is false.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 9bf9524934..66e01464b5 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -8,7 +8,6 @@ test_description='per path merge controlled by merge attribute' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -118,6 +117,14 @@ test_expect_success 'retry the merge with longer context' ' grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual ' +test_expect_success 'invalid conflict-marker-size 3a' ' + cp .gitattributes .gitattributes.bak && + echo "text conflict-marker-size=3a" >>.gitattributes && + test_when_finished "mv .gitattributes.bak .gitattributes" && + git checkout -m text 2>err && + test_grep "warning: invalid marker-size ${SQ}3a${SQ}, expecting an integer" err +' + test_expect_success 'custom merge backend' ' echo "* merge=union" >.gitattributes && diff --git a/t/t6407-merge-binary.sh b/t/t6407-merge-binary.sh index 0753fc95f4..e8a28717ce 100755 --- a/t/t6407-merge-binary.sh +++ b/t/t6407-merge-binary.sh @@ -5,7 +5,6 @@ test_description='ask merge-recursive to merge binary files' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6408-merge-up-to-date.sh b/t/t6408-merge-up-to-date.sh index 8a1ba6d23a..7763c1ba98 100755 --- a/t/t6408-merge-up-to-date.sh +++ b/t/t6408-merge-up-to-date.sh @@ -2,7 +2,6 @@ test_description='merge fast-forward and up to date' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6411-merge-filemode.sh b/t/t6411-merge-filemode.sh index b6182723aa..6ae2489286 100755 --- a/t/t6411-merge-filemode.sh +++ b/t/t6411-merge-filemode.sh @@ -4,7 +4,6 @@ test_description='merge: handle file mode' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up mode change in one branch' ' diff --git a/t/t6412-merge-large-rename.sh b/t/t6412-merge-large-rename.sh index d0863a8fb5..ca018d11f5 100755 --- a/t/t6412-merge-large-rename.sh +++ b/t/t6412-merge-large-rename.sh @@ -4,7 +4,6 @@ test_description='merging with large rename matrix' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh count() { diff --git a/t/t6413-merge-crlf.sh b/t/t6413-merge-crlf.sh index 647ea1e838..cd6adf6caa 100755 --- a/t/t6413-merge-crlf.sh +++ b/t/t6413-merge-crlf.sh @@ -11,7 +11,6 @@ test_description='merge conflict in crlf repo GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6414-merge-rename-nocruft.sh b/t/t6414-merge-rename-nocruft.sh index 69fc1c9e69..d7e3c1fa6e 100755 --- a/t/t6414-merge-rename-nocruft.sh +++ b/t/t6414-merge-rename-nocruft.sh @@ -4,7 +4,6 @@ test_description='Merge-recursive merging renames' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6415-merge-dir-to-symlink.sh b/t/t6415-merge-dir-to-symlink.sh index ae00492c76..2655e295f5 100755 --- a/t/t6415-merge-dir-to-symlink.sh +++ b/t/t6415-merge-dir-to-symlink.sh @@ -4,7 +4,6 @@ test_description='merging when a directory was replaced with a symlink' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create a commit where dir a/b changed to symlink' ' diff --git a/t/t6416-recursive-corner-cases.sh b/t/t6416-recursive-corner-cases.sh index 5f414abc89..17b54d625d 100755 --- a/t/t6416-recursive-corner-cases.sh +++ b/t/t6416-recursive-corner-cases.sh @@ -5,7 +5,6 @@ test_description='recursive merge corner cases involving criss-cross merges' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6417-merge-ours-theirs.sh b/t/t6417-merge-ours-theirs.sh index 482b73a998..62d1406119 100755 --- a/t/t6417-merge-ours-theirs.sh +++ b/t/t6417-merge-ours-theirs.sh @@ -4,7 +4,6 @@ test_description='Merge-recursive ours and theirs variants' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6418-merge-text-auto.sh b/t/t6418-merge-text-auto.sh index 48a62cb855..41288a60ce 100755 --- a/t/t6418-merge-text-auto.sh +++ b/t/t6418-merge-text-auto.sh @@ -15,7 +15,6 @@ test_description='CRLF merge conflict across text=auto change GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh index 711b709e75..b99f29ef9b 100755 --- a/t/t6421-merge-partial-clone.sh +++ b/t/t6421-merge-partial-clone.sh @@ -230,8 +230,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded for single relev grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual && test_cmp expect actual && - # Check the number of fetch commands exec-ed - grep d0.*fetch.negotiationAlgorithm trace.output >fetches && + # Check the number of fetch commands exec-ed by filtering trace to + # child_start events by the top-level program (2nd field == d0) + grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches && test_line_count = 2 fetches && git rev-list --objects --all --missing=print | @@ -318,8 +319,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded when a directory grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual && test_cmp expect actual && - # Check the number of fetch commands exec-ed - grep d0.*fetch.negotiationAlgorithm trace.output >fetches && + # Check the number of fetch commands exec-ed by filtering trace to + # child_start events by the top-level program (2nd field == d0) + grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches && test_line_count = 1 fetches && git rev-list --objects --all --missing=print | @@ -422,8 +424,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded with lots of ren grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual && test_cmp expect actual && - # Check the number of fetch commands exec-ed - grep d0.*fetch.negotiationAlgorithm trace.output >fetches && + # Check the number of fetch commands exec-ed by filtering trace to + # child_start events by the top-level program (2nd field == d0) + grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches && test_line_count = 4 fetches && git rev-list --objects --all --missing=print | diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh index 80d7b5eaba..62b49c67e2 100755 --- a/t/t6422-merge-rename-corner-cases.sh +++ b/t/t6422-merge-rename-corner-cases.sh @@ -6,7 +6,6 @@ test_description="recursive merge corner cases w/ renames but not criss-crosses" GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6425-merge-rename-delete.sh b/t/t6425-merge-rename-delete.sh index b95b064311..c15d031b16 100755 --- a/t/t6425-merge-rename-delete.sh +++ b/t/t6425-merge-rename-delete.sh @@ -4,7 +4,6 @@ test_description='Merge-recursive rename/delete conflict message' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'rename/delete' ' diff --git a/t/t6426-merge-skip-unneeded-updates.sh b/t/t6426-merge-skip-unneeded-updates.sh index 62f0180325..b059475ed0 100755 --- a/t/t6426-merge-skip-unneeded-updates.sh +++ b/t/t6426-merge-skip-unneeded-updates.sh @@ -22,7 +22,6 @@ test_description="merge cases" # underscore notation is to differentiate different # files that might be renamed into each other's paths.) -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6427-diff3-conflict-markers.sh b/t/t6427-diff3-conflict-markers.sh index a13271b349..dd5fe6a402 100755 --- a/t/t6427-diff3-conflict-markers.sh +++ b/t/t6427-diff3-conflict-markers.sh @@ -5,7 +5,6 @@ test_description='recursive merge diff3 style conflict markers' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Setup: diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index cb1c4ceef7..0f39ed0d08 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -2,7 +2,6 @@ test_description="remember regular & dir renames in sequence of merges" -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh index 555f00f78a..ca15e6dd6d 100755 --- a/t/t6430-merge-recursive.sh +++ b/t/t6430-merge-recursive.sh @@ -5,7 +5,6 @@ test_description='merge-recursive backend test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6431-merge-criscross.sh b/t/t6431-merge-criscross.sh index 3fe14cd73e..3824756a02 100755 --- a/t/t6431-merge-criscross.sh +++ b/t/t6431-merge-criscross.sh @@ -2,7 +2,6 @@ test_description='merge-recursive backend test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # A <- create some files diff --git a/t/t6432-merge-recursive-space-options.sh b/t/t6432-merge-recursive-space-options.sh index c93538b0c3..db4b77e63d 100755 --- a/t/t6432-merge-recursive-space-options.sh +++ b/t/t6432-merge-recursive-space-options.sh @@ -14,7 +14,6 @@ test_description='merge-recursive space options GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b diff --git a/t/t6433-merge-toplevel.sh b/t/t6433-merge-toplevel.sh index ed7866d3e9..0f611c4003 100755 --- a/t/t6433-merge-toplevel.sh +++ b/t/t6433-merge-toplevel.sh @@ -5,7 +5,6 @@ test_description='"git merge" top-level frontend' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh t3033_reset () { diff --git a/t/t6434-merge-recursive-rename-options.sh b/t/t6434-merge-recursive-rename-options.sh index df1d0c156c..a11707835b 100755 --- a/t/t6434-merge-recursive-rename-options.sh +++ b/t/t6434-merge-recursive-rename-options.sh @@ -29,7 +29,6 @@ mentions this in a different context). GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh get_expected_stages () { diff --git a/t/t6435-merge-sparse.sh b/t/t6435-merge-sparse.sh index 78628fb248..fde4aa3cd1 100755 --- a/t/t6435-merge-sparse.sh +++ b/t/t6435-merge-sparse.sh @@ -3,7 +3,6 @@ test_description='merge with sparse files' TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # test_file $filename $content diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh index ccc620477d..4f4376421e 100755 --- a/t/t6436-merge-overwrite.sh +++ b/t/t6436-merge-overwrite.sh @@ -7,7 +7,6 @@ Do not overwrite changes.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index 7a3f1cb27c..4815559157 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -8,7 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6438-submodule-directory-file-conflicts.sh b/t/t6438-submodule-directory-file-conflicts.sh index 3594190af8..8df67a0ef9 100755 --- a/t/t6438-submodule-directory-file-conflicts.sh +++ b/t/t6438-submodule-directory-file-conflicts.sh @@ -2,7 +2,6 @@ test_description='merge can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh index 0cbec57cda..55bd744a3f 100755 --- a/t/t6439-merge-co-error-msgs.sh +++ b/t/t6439-merge-co-error-msgs.sh @@ -5,7 +5,6 @@ test_description='unpack-trees error messages' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh @@ -65,7 +64,7 @@ Please move or remove them before you merge. Aborting EOF -test_expect_success 'untracked files or local changes ovewritten by merge' ' +test_expect_success 'untracked files or local changes overwritten by merge' ' git add two && git add three && git add four && diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 1b5909d1b7..5378455968 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -338,14 +338,14 @@ test_expect_success 'gc.maxCruftSize sets appropriate repack options' ' test_subcommand $cruft_max_size_opts --max-cruft-size=3145728 <trace2.txt ' -run_and_wait_for_auto_gc () { +run_and_wait_for_gc () { # We read stdout from gc for the side effect of waiting until the # background gc process exits, closing its fd 9. Furthermore, the # variable assignment from a command substitution preserves the # exit status of the main gc process. # Note: this fd trickery doesn't work on Windows, but there is no # need to, because on Win the auto gc always runs in the foreground. - doesnt_matter=$(git gc --auto 9>&1) + doesnt_matter=$(git gc "$@" 9>&1) } test_expect_success 'background auto gc does not run if gc.log is present and recent but does if it is old' ' @@ -361,7 +361,7 @@ test_expect_success 'background auto gc does not run if gc.log is present and re test-tool chmtime =-345600 .git/gc.log && git gc --auto && test_config gc.logexpiry 2.days && - run_and_wait_for_auto_gc && + run_and_wait_for_gc --auto && ls .git/objects/pack/pack-*.pack >packs && test_line_count = 1 packs ' @@ -391,11 +391,48 @@ test_expect_success 'background auto gc respects lock for all operations' ' printf "%d %s" "$shell_pid" "$hostname" >.git/gc.pid && # our gc should exit zero without doing anything - run_and_wait_for_auto_gc && + run_and_wait_for_gc --auto && (ls -1 .git/refs/heads .git/reftable >actual || true) && test_cmp expect actual ' +test_expect_success '--detach overrides gc.autoDetach=false' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + # Prepare the repository such that git-gc(1) ends up repacking. + test_commit "$(test_oid blob17_1)" && + test_commit "$(test_oid blob17_2)" && + git config gc.autodetach false && + git config gc.auto 2 && + + # Note that we cannot use `test_cmp` here to compare stderr + # because it may contain output from `set -x`. + run_and_wait_for_gc --auto --detach 2>actual && + test_grep "Auto packing the repository in background for optimum performance." actual + ) +' + +test_expect_success '--no-detach overrides gc.autoDetach=true' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + # Prepare the repository such that git-gc(1) ends up repacking. + test_commit "$(test_oid blob17_1)" && + test_commit "$(test_oid blob17_2)" && + git config gc.autodetach true && + git config gc.auto 2 && + + GIT_PROGRESS_DELAY=0 git gc --auto --no-detach 2>output && + test_grep "Auto packing the repository for optimum performance." output && + test_grep "Collecting referenced commits: 2, done." output + ) +' + # DO NOT leave a detached auto gc process running near the end of the # test script: it can run long enough in the background to racily # interfere with the cleanup in 'test_done'. diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh index 4521508b83..ddef1ca391 100755 --- a/t/t6501-freshen-objects.sh +++ b/t/t6501-freshen-objects.sh @@ -28,7 +28,6 @@ test_description='check pruning of dependent objects' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We care about reachability, so we do not want to use diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index b330945f49..2591f8b8b3 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -612,4 +612,125 @@ test_expect_success 'for-each-ref merged:none' ' --format="%(refname)" --stdin ' +# For get_branch_base_for_tip, we only care about +# first-parent history. Here is the test graph with +# second parents removed: +# +# (10,10) +# / +# (10,9) (9,10) +# / / +# (10,8) (9,9) (8,10) +# / / / +# ( continued...) +# \ / / / +# (3,1) (2,2) (1,3) +# \ / / +# (2,1) (1,2) +# \ / +# (1,1) +# +# In short, for a commit (i,j), the first-parent history +# walks all commits (i, k) with k from j to 1, then the +# commits (l, 1) with l from i to 1. + +test_expect_success 'get_branch_base_for_tip: none reach' ' + # (2,3) branched from the first tip (i,4) in X with i > 2 + cat >input <<-\EOF && + A:commit-2-3 + X:commit-1-2 + X:commit-1-4 + X:commit-4-4 + X:commit-8-4 + X:commit-10-4 + EOF + echo "get_branch_base_for_tip(A,X):2" >expect && + test_all_modes get_branch_base_for_tip +' + +test_expect_success 'get_branch_base_for_tip: equal to tip' ' + # (2,3) branched from the first tip (i,4) in X with i > 2 + cat >input <<-\EOF && + A:commit-8-4 + X:commit-1-2 + X:commit-1-4 + X:commit-4-4 + X:commit-8-4 + X:commit-10-4 + EOF + echo "get_branch_base_for_tip(A,X):3" >expect && + test_all_modes get_branch_base_for_tip +' + +test_expect_success 'get_branch_base_for_tip: all reach tip' ' + # (2,3) branched from the first tip (i,4) in X with i > 2 + cat >input <<-\EOF && + A:commit-4-1 + X:commit-4-2 + X:commit-5-1 + EOF + echo "get_branch_base_for_tip(A,X):0" >expect && + test_all_modes get_branch_base_for_tip +' + +test_expect_success 'for-each-ref is-base: none reach' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + refs/heads/commit-8-4 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1: + refs/heads/commit-4-2:(commit-2-3) + refs/heads/commit-4-4: + refs/heads/commit-8-4: + EOF + run_all_modes git for-each-ref \ + --format="%(refname):%(is-base:commit-2-3)" --stdin +' + +test_expect_success 'for-each-ref is-base: all reach' ' + cat >input <<-\EOF && + refs/heads/commit-4-2 + refs/heads/commit-5-1 + EOF + cat >expect <<-\EOF && + refs/heads/commit-4-2:(commit-4-1) + refs/heads/commit-5-1: + EOF + run_all_modes git for-each-ref \ + --format="%(refname):%(is-base:commit-4-1)" --stdin +' + +test_expect_success 'for-each-ref is-base: equal to tip' ' + cat >input <<-\EOF && + refs/heads/commit-4-2 + refs/heads/commit-5-1 + EOF + cat >expect <<-\EOF && + refs/heads/commit-4-2:(commit-4-2) + refs/heads/commit-5-1: + EOF + run_all_modes git for-each-ref \ + --format="%(refname):%(is-base:commit-4-2)" --stdin +' + +test_expect_success 'for-each-ref is-base:multiple' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + refs/heads/commit-8-4 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1[-] + refs/heads/commit-4-2[(commit-2-3)-] + refs/heads/commit-4-4[-] + refs/heads/commit-8-4[-(commit-6-5)] + EOF + run_all_modes git for-each-ref \ + --format="%(refname)[%(is-base:commit-2-3)-%(is-base:commit-6-5)]" --stdin +' + test_done diff --git a/t/t6700-tree-depth.sh b/t/t6700-tree-depth.sh index 9e70a7c763..0f6a2ad9b5 100755 --- a/t/t6700-tree-depth.sh +++ b/t/t6700-tree-depth.sh @@ -2,7 +2,6 @@ test_description='handling of deep trees in various commands' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We'll test against two depths here: a small one that will let us check the diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 86258f9f43..25334b5062 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -2,7 +2,6 @@ test_description='git mv in subdirs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-data.sh @@ -551,4 +550,16 @@ test_expect_success 'moving nested submodules' ' git status ' +test_expect_failure 'nonsense mv triggers assertion failure and partially updated index' ' + test_when_finished git reset --hard HEAD && + git reset --hard HEAD && + mkdir -p a && + mkdir -p b && + >a/a.txt && + git add a/a.txt && + test_must_fail git mv a/a.txt a b && + git status --porcelain >actual && + grep "^A[ ]*a/a.txt$" actual +' + test_done diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh index 57969ce805..4d3f221224 100755 --- a/t/t7002-mv-sparse-checkout.sh +++ b/t/t7002-mv-sparse-checkout.sh @@ -2,7 +2,6 @@ test_description='git mv in sparse working trees' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh setup_sparse_checkout () { @@ -33,7 +32,7 @@ test_expect_success 'setup' " hint: If you intend to update such entries, try one of the following: hint: * Use the --sparse option. hint: * Disable or modify the sparsity rules. - hint: Disable this message with \"git config advice.updateSparsePath false\" + hint: Disable this message with \"git config set advice.updateSparsePath false\" EOF cat >dirty_error_header <<-EOF && @@ -46,7 +45,7 @@ test_expect_success 'setup' " hint: To correct the sparsity of these paths, do the following: hint: * Use \"git add --sparse <paths>\" to update the index hint: * Use \"git sparse-checkout reapply\" to apply the sparsity rules - hint: Disable this message with \"git config advice.updateSparsePath false\" + hint: Disable this message with \"git config set advice.updateSparsePath false\" EOF " diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index fa6336edf9..10835631ca 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -61,8 +61,9 @@ test_expect_success 'sort tags, ignore case' ' ) ' -test_expect_success 'looking for a tag in an empty tree should fail' \ - '! (tag_exists mytag)' +test_expect_success 'looking for a tag in an empty tree should fail' ' + ! (tag_exists mytag) +' test_expect_success 'creating a tag in an empty tree should fail' ' test_must_fail git tag mynotag && @@ -90,6 +91,18 @@ test_expect_success 'creating a tag using default HEAD should succeed' ' test_must_fail git reflog exists refs/tags/mytag ' +test_expect_success 'HEAD is forbidden as a tagname' ' + test_when_finished "git update-ref --no-deref -d refs/tags/HEAD || :" && + test_must_fail git tag HEAD && + test_must_fail git tag -a -m "useless" HEAD +' + +test_expect_success '"git tag" can remove a tag named HEAD' ' + test_when_finished "git update-ref --no-deref -d refs/tags/HEAD || :" && + git update-ref refs/tags/HEAD HEAD && + git tag -d HEAD +' + test_expect_success 'creating a tag with --create-reflog should create reflog' ' git log -1 \ --format="format:tag: tagging %h (%s, %cd)%n" \ @@ -129,10 +142,10 @@ test_expect_success 'listing all tags if one exists should succeed' ' git tag ' -cat >expect <<EOF -mytag -EOF test_expect_success 'Multiple -l or --list options are equivalent to one -l option' ' + cat >expect <<-\EOF && + mytag + EOF git tag -l -l >actual && test_cmp expect actual && git tag --list --list >actual && @@ -148,32 +161,33 @@ test_expect_success 'listing all tags if one exists should output that tag' ' # pattern matching: -test_expect_success 'listing a tag using a matching pattern should succeed' \ - 'git tag -l mytag' +test_expect_success 'listing a tag using a matching pattern should succeed' ' + git tag -l mytag +' -test_expect_success 'listing a tag with --ignore-case' \ - 'test $(git tag -l --ignore-case MYTAG) = mytag' +test_expect_success 'listing a tag with --ignore-case' ' + test $(git tag -l --ignore-case MYTAG) = mytag +' -test_expect_success \ - 'listing a tag using a matching pattern should output that tag' \ - 'test $(git tag -l mytag) = mytag' +test_expect_success 'listing a tag using a matching pattern should output that tag' ' + test $(git tag -l mytag) = mytag +' -test_expect_success \ - 'listing tags using a non-matching pattern should succeed' \ - 'git tag -l xxx' +test_expect_success 'listing tags using a non-matching pattern should succeed' ' + git tag -l xxx +' -test_expect_success \ - 'listing tags using a non-matching pattern should output nothing' \ - 'test $(git tag -l xxx | wc -l) -eq 0' +test_expect_success 'listing tags using a non-matching pattern should output nothing' ' + test $(git tag -l xxx | wc -l) -eq 0 +' # special cases for creating tags: -test_expect_success \ - 'trying to create a tag with the name of one existing should fail' \ - 'test_must_fail git tag mytag' +test_expect_success 'trying to create a tag with the name of one existing should fail' ' + test_must_fail git tag mytag +' -test_expect_success \ - 'trying to create a tag with a non-valid name should fail' ' +test_expect_success 'trying to create a tag with a non-valid name should fail' ' test $(git tag -l | wc -l) -eq 1 && test_must_fail git tag "" && test_must_fail git tag .othertag && @@ -207,19 +221,19 @@ test_expect_success 'trying to delete an unknown tag should fail' ' test_must_fail git tag -d unknown-tag ' -cat >expect <<EOF -myhead -mytag -EOF -test_expect_success \ - 'trying to delete tags without params should succeed and do nothing' ' - git tag -l > actual && test_cmp expect actual && +test_expect_success 'trying to delete tags without params should succeed and do nothing' ' + cat >expect <<-\EOF && + myhead + mytag + EOF + git tag -l >actual && + test_cmp expect actual && git tag -d && - git tag -l > actual && test_cmp expect actual + git tag -l >actual && + test_cmp expect actual ' -test_expect_success \ - 'deleting two existing tags in one command should succeed' ' +test_expect_success 'deleting two existing tags in one command should succeed' ' tag_exists mytag && tag_exists myhead && git tag -d mytag myhead && @@ -227,15 +241,13 @@ test_expect_success \ ! tag_exists myhead ' -test_expect_success \ - 'creating a tag with the name of another deleted one should succeed' ' +test_expect_success 'creating a tag with the name of another deleted one should succeed' ' ! tag_exists mytag && git tag mytag && tag_exists mytag ' -test_expect_success \ - 'trying to delete two tags, existing and not, should fail in the 2nd' ' +test_expect_success 'trying to delete two tags, existing and not, should fail in the 2nd' ' tag_exists mytag && ! tag_exists nonexistingtag && test_must_fail git tag -d mytag nonexistingtag && @@ -243,23 +255,24 @@ test_expect_success \ ! tag_exists nonexistingtag ' -test_expect_success 'trying to delete an already deleted tag should fail' \ - 'test_must_fail git tag -d mytag' +test_expect_success 'trying to delete an already deleted tag should fail' ' + test_must_fail git tag -d mytag +' # listing various tags with pattern matching: -cat >expect <<EOF -a1 -aa1 -cba -t210 -t211 -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -EOF test_expect_success 'listing all tags should print them ordered' ' + cat >expect <<-\EOF && + a1 + aa1 + cba + t210 + t211 + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + EOF git tag v1.0.1 && git tag t211 && git tag aa1 && @@ -269,91 +282,89 @@ test_expect_success 'listing all tags should print them ordered' ' git tag a1 && git tag v1.0 && git tag t210 && - git tag -l > actual && + git tag -l >actual && test_cmp expect actual && - git tag > actual && + git tag >actual && test_cmp expect actual ' -cat >expect <<EOF -a1 -aa1 -cba -EOF -test_expect_success \ - 'listing tags with substring as pattern must print those matching' ' +test_expect_success 'listing tags with substring as pattern must print those matching' ' + cat >expect <<-\EOF && + a1 + aa1 + cba + EOF rm *a* && - git tag -l "*a*" > current && + git tag -l "*a*" >current && test_cmp expect current ' -cat >expect <<EOF -v0.2.1 -v1.0.1 -EOF -test_expect_success \ - 'listing tags with a suffix as pattern must print those matching' ' - git tag -l "*.1" > actual && +test_expect_success 'listing tags with a suffix as pattern must print those matching' ' + cat >expect <<-\EOF && + v0.2.1 + v1.0.1 + EOF + git tag -l "*.1" >actual && test_cmp expect actual ' -cat >expect <<EOF -t210 -t211 -EOF -test_expect_success \ - 'listing tags with a prefix as pattern must print those matching' ' - git tag -l "t21*" > actual && +test_expect_success 'listing tags with a prefix as pattern must print those matching' ' + cat >expect <<-\EOF && + t210 + t211 + EOF + git tag -l "t21*" >actual && test_cmp expect actual ' -cat >expect <<EOF -a1 -EOF -test_expect_success \ - 'listing tags using a name as pattern must print that one matching' ' - git tag -l a1 > actual && +test_expect_success 'listing tags using a name as pattern must print that one matching' ' + cat >expect <<-\EOF && + a1 + EOF + git tag -l a1 >actual && test_cmp expect actual ' -cat >expect <<EOF -v1.0 -EOF -test_expect_success \ - 'listing tags using a name as pattern must print that one matching' ' - git tag -l v1.0 > actual && +test_expect_success 'listing tags using a name as pattern must print that one matching' ' + cat >expect <<-\EOF && + v1.0 + EOF + git tag -l v1.0 >actual && test_cmp expect actual ' -cat >expect <<EOF -v1.0.1 -v1.1.3 -EOF -test_expect_success \ - 'listing tags with ? in the pattern should print those matching' ' - git tag -l "v1.?.?" > actual && +test_expect_success 'listing tags with ? in the pattern should print those matching' ' + cat >expect <<-\EOF && + v1.0.1 + v1.1.3 + EOF + git tag -l "v1.?.?" >actual && test_cmp expect actual ' -test_expect_success \ - 'listing tags using v.* should print nothing because none have v.' ' - git tag -l "v.*" > actual && +test_expect_success 'listing tags using v.* should print nothing because none have v.' ' + git tag -l "v.*" >actual && test_must_be_empty actual ' -cat >expect <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -EOF -test_expect_success \ - 'listing tags using v* should print only those having v' ' - git tag -l "v*" > actual && +test_expect_success 'listing tags using v* should print only those having v' ' + cat >expect <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + EOF + git tag -l "v*" >actual && test_cmp expect actual ' test_expect_success 'tag -l can accept multiple patterns' ' + cat >expect <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + EOF git tag -l "v1*" "v0*" >actual && test_cmp expect actual ' @@ -367,16 +378,22 @@ test_expect_success 'tag -l can accept multiple patterns' ' # out if we're going to break this long-documented form of taking # multiple patterns. test_expect_success 'tag -l <pattern> -l <pattern> works, as our buggy documentation previously suggested' ' + cat >expect <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + EOF git tag -l "v1*" -l "v0*" >actual && test_cmp expect actual ' test_expect_success 'listing tags in column' ' COLUMNS=41 git tag -l --column=row >actual && - cat >expected <<\EOF && -a1 aa1 cba t210 t211 -v0.2.1 v1.0 v1.0.1 v1.1.3 -EOF + cat >expected <<-\EOF && + a1 aa1 cba t210 t211 + v0.2.1 v1.0 v1.0.1 v1.1.3 + EOF test_cmp expected actual ' @@ -384,10 +401,10 @@ test_expect_success 'listing tags in column with column.*' ' test_config column.tag row && test_config column.ui dense && COLUMNS=40 git tag -l >actual && - cat >expected <<\EOF && -a1 aa1 cba t210 t211 -v0.2.1 v1.0 v1.0.1 v1.1.3 -EOF + cat >expected <<-\EOF && + a1 aa1 cba t210 t211 + v0.2.1 v1.0 v1.0.1 v1.1.3 + EOF test_cmp expected actual ' @@ -398,39 +415,39 @@ test_expect_success 'listing tag with -n --column should fail' ' test_expect_success 'listing tags -n in column with column.ui ignored' ' test_config column.ui "row dense" && COLUMNS=40 git tag -l -n >actual && - cat >expected <<\EOF && -a1 Foo -aa1 Foo -cba Foo -t210 Foo -t211 Foo -v0.2.1 Foo -v1.0 Foo -v1.0.1 Foo -v1.1.3 Foo -EOF + cat >expected <<-\EOF && + a1 Foo + aa1 Foo + cba Foo + t210 Foo + t211 Foo + v0.2.1 Foo + v1.0 Foo + v1.0.1 Foo + v1.1.3 Foo + EOF test_cmp expected actual ' # creating and verifying lightweight tags: -test_expect_success \ - 'a non-annotated tag created without parameters should point to HEAD' ' +test_expect_success 'a non-annotated tag created without parameters should point to HEAD' ' git tag non-annotated-tag && test $(git cat-file -t non-annotated-tag) = commit && test $(git rev-parse non-annotated-tag) = $(git rev-parse HEAD) ' -test_expect_success 'trying to verify an unknown tag should fail' \ - 'test_must_fail git tag -v unknown-tag' +test_expect_success 'trying to verify an unknown tag should fail' ' + test_must_fail git tag -v unknown-tag +' -test_expect_success \ - 'trying to verify a non-annotated and non-signed tag should fail' \ - 'test_must_fail git tag -v non-annotated-tag' +test_expect_success 'trying to verify a non-annotated and non-signed tag should fail' ' + test_must_fail git tag -v non-annotated-tag +' -test_expect_success \ - 'trying to verify many non-annotated or unknown tags, should fail' \ - 'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2' +test_expect_success 'trying to verify many non-annotated or unknown tags, should fail' ' + test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2 +' # creating annotated tags: @@ -449,83 +466,78 @@ tagger C O Mitter <committer@example.com> $4 -0700 EOF } -commit=$(git rev-parse HEAD) -time=$test_tick - -get_tag_header annotated-tag $commit commit $time >expect -echo "A message" >>expect -test_expect_success \ - 'creating an annotated tag with -m message should succeed' ' +test_expect_success 'creating an annotated tag with -m message should succeed' ' + commit=$(git rev-parse HEAD) && + time=$test_tick && + get_tag_header annotated-tag $commit commit $time >expect && + echo "A message" >>expect && git tag -m "A message" annotated-tag && get_tag_msg annotated-tag >actual && test_cmp expect actual ' -get_tag_header annotated-tag-edit $commit commit $time >expect -echo "An edited message" >>expect test_expect_success 'set up editor' ' write_script fakeeditor <<-\EOF sed -e "s/A message/An edited message/g" <"$1" >"$1-" mv "$1-" "$1" EOF ' -test_expect_success \ - 'creating an annotated tag with -m message --edit should succeed' ' + +test_expect_success 'creating an annotated tag with -m message --edit should succeed' ' + get_tag_header annotated-tag-edit $commit commit $time >expect && + echo "An edited message" >>expect && GIT_EDITOR=./fakeeditor git tag -m "A message" --edit annotated-tag-edit && get_tag_msg annotated-tag-edit >actual && test_cmp expect actual ' -cat >msgfile <<EOF -Another message -in a file. -EOF -get_tag_header file-annotated-tag $commit commit $time >expect -cat msgfile >>expect -test_expect_success \ - 'creating an annotated tag with -F messagefile should succeed' ' +test_expect_success 'creating an annotated tag with -F messagefile should succeed' ' + cat >msgfile <<-\EOF && + Another message + in a file. + EOF + get_tag_header file-annotated-tag $commit commit $time >expect && + cat msgfile >>expect && git tag -F msgfile file-annotated-tag && get_tag_msg file-annotated-tag >actual && test_cmp expect actual ' -get_tag_header file-annotated-tag-edit $commit commit $time >expect -sed -e "s/Another message/Another edited message/g" msgfile >>expect test_expect_success 'set up editor' ' write_script fakeeditor <<-\EOF sed -e "s/Another message/Another edited message/g" <"$1" >"$1-" mv "$1-" "$1" EOF ' -test_expect_success \ - 'creating an annotated tag with -F messagefile --edit should succeed' ' + +test_expect_success 'creating an annotated tag with -F messagefile --edit should succeed' ' + get_tag_header file-annotated-tag-edit $commit commit $time >expect && + sed -e "s/Another message/Another edited message/g" msgfile >>expect && GIT_EDITOR=./fakeeditor git tag -F msgfile --edit file-annotated-tag-edit && get_tag_msg file-annotated-tag-edit >actual && test_cmp expect actual ' -cat >inputmsg <<EOF -A message from the -standard input -EOF -get_tag_header stdin-annotated-tag $commit commit $time >expect -cat inputmsg >>expect test_expect_success 'creating an annotated tag with -F - should succeed' ' + cat >inputmsg <<-\EOF && + A message from the + standard input + EOF + get_tag_header stdin-annotated-tag $commit commit $time >expect && + cat inputmsg >>expect && git tag -F - stdin-annotated-tag <inputmsg && get_tag_msg stdin-annotated-tag >actual && test_cmp expect actual ' -test_expect_success \ - 'trying to create a tag with a non-existing -F file should fail' ' +test_expect_success 'trying to create a tag with a non-existing -F file should fail' ' ! test -f nonexistingfile && ! tag_exists notag && test_must_fail git tag -F nonexistingfile notag && ! tag_exists notag ' -test_expect_success \ - 'trying to create tags giving both -m or -F options should fail' ' +test_expect_success 'trying to create tags giving both -m or -F options should fail' ' echo "message file 1" >msgfile1 && ! tag_exists msgtag && test_must_fail git tag -m "message 1" -F msgfile1 msgtag && @@ -539,67 +551,61 @@ test_expect_success \ # blank and empty messages: -get_tag_header empty-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with an empty -m message should succeed' ' +test_expect_success 'creating a tag with an empty -m message should succeed' ' + get_tag_header empty-annotated-tag $commit commit $time >expect && git tag -m "" empty-annotated-tag && get_tag_msg empty-annotated-tag >actual && test_cmp expect actual ' ->emptyfile -get_tag_header emptyfile-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with an empty -F messagefile should succeed' ' +test_expect_success 'creating a tag with an empty -F messagefile should succeed' ' + >emptyfile && + get_tag_header emptyfile-annotated-tag $commit commit $time >expect && git tag -F emptyfile emptyfile-annotated-tag && get_tag_msg emptyfile-annotated-tag >actual && test_cmp expect actual ' -printf '\n\n \n\t\nLeading blank lines\n' >blanksfile -printf '\n\t \t \nRepeated blank lines\n' >>blanksfile -printf '\n\n\nTrailing spaces \t \n' >>blanksfile -printf '\nTrailing blank lines\n\n\t \n\n' >>blanksfile -get_tag_header blanks-annotated-tag $commit commit $time >expect -cat >>expect <<EOF -Leading blank lines +test_expect_success 'extra blanks in the message for an annotated tag should be removed' ' + printf "\n\n \n\t\nLeading blank lines\n" >blanksfile && + printf "\n\t \t \nRepeated blank lines\n" >>blanksfile && + printf "\n\n\nTrailing spaces \t \n" >>blanksfile && + printf "\nTrailing blank lines\n\n\t \n\n" >>blanksfile && + get_tag_header blanks-annotated-tag $commit commit $time >expect && + cat >>expect <<-\EOF && + Leading blank lines -Repeated blank lines + Repeated blank lines -Trailing spaces + Trailing spaces -Trailing blank lines -EOF -test_expect_success \ - 'extra blanks in the message for an annotated tag should be removed' ' + Trailing blank lines + EOF git tag -F blanksfile blanks-annotated-tag && get_tag_msg blanks-annotated-tag >actual && test_cmp expect actual ' -get_tag_header blank-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with blank -m message with spaces should succeed' ' +test_expect_success 'creating a tag with blank -m message with spaces should succeed' ' + get_tag_header blank-annotated-tag $commit commit $time >expect && git tag -m " " blank-annotated-tag && get_tag_msg blank-annotated-tag >actual && test_cmp expect actual ' -echo ' ' >blankfile -echo '' >>blankfile -echo ' ' >>blankfile -get_tag_header blankfile-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with blank -F messagefile with spaces should succeed' ' +test_expect_success 'creating a tag with blank -F messagefile with spaces should succeed' ' + echo " " >blankfile && + echo "" >>blankfile && + echo " " >>blankfile && + get_tag_header blankfile-annotated-tag $commit commit $time >expect && git tag -F blankfile blankfile-annotated-tag && get_tag_msg blankfile-annotated-tag >actual && test_cmp expect actual ' -printf ' ' >blanknonlfile -get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with -F file of spaces and no newline should succeed' ' +test_expect_success 'creating a tag with -F file of spaces and no newline should succeed' ' + printf " " >blanknonlfile && + get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect && git tag -F blanknonlfile blanknonlfile-annotated-tag && get_tag_msg blanknonlfile-annotated-tag >actual && test_cmp expect actual @@ -607,62 +613,58 @@ test_expect_success \ # messages with commented lines: -cat >commentsfile <<EOF -# A comment +test_expect_success 'creating a tag using a -F messagefile with #comments should succeed' ' + cat >commentsfile <<-\EOF && + # A comment -############ -The message. -############ -One line. + ############ + The message. + ############ + One line. -# commented lines -# commented lines + # commented lines + # commented lines -Another line. -# comments + Another line. + # comments -Last line. -EOF -get_tag_header comments-annotated-tag $commit commit $time >expect -cat >>expect <<EOF -The message. -One line. + Last line. + EOF + get_tag_header comments-annotated-tag $commit commit $time >expect && + cat >>expect <<-\EOF && + The message. + One line. -Another line. + Another line. -Last line. -EOF -test_expect_success \ - 'creating a tag using a -F messagefile with #comments should succeed' ' + Last line. + EOF git tag -F commentsfile comments-annotated-tag && get_tag_msg comments-annotated-tag >actual && test_cmp expect actual ' -get_tag_header comment-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with a #comment in the -m message should succeed' ' +test_expect_success 'creating a tag with a #comment in the -m message should succeed' ' + get_tag_header comment-annotated-tag $commit commit $time >expect && git tag -m "#comment" comment-annotated-tag && get_tag_msg comment-annotated-tag >actual && test_cmp expect actual ' -echo '#comment' >commentfile -echo '' >>commentfile -echo '####' >>commentfile -get_tag_header commentfile-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with #comments in the -F messagefile should succeed' ' +test_expect_success 'creating a tag with #comments in the -F messagefile should succeed' ' + echo "#comment" >commentfile && + echo "" >>commentfile && + echo "####" >>commentfile && + get_tag_header commentfile-annotated-tag $commit commit $time >expect && git tag -F commentfile commentfile-annotated-tag && get_tag_msg commentfile-annotated-tag >actual && test_cmp expect actual ' -printf '#comment' >commentnonlfile -get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect -test_expect_success \ - 'creating a tag with a file of #comment and no newline should succeed' ' +test_expect_success 'creating a tag with a file of #comment and no newline should succeed' ' + printf "#comment" >commentnonlfile && + get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect && git tag -F commentnonlfile commentnonlfile-annotated-tag && get_tag_msg commentnonlfile-annotated-tag >actual && test_cmp expect actual @@ -779,8 +781,7 @@ test_expect_success 'bad editor causes panic when only --trailer is given' ' # listing messages for annotated non-signed tags: -test_expect_success \ - 'listing the one-line message of a non-signed tag should succeed' ' +test_expect_success 'listing the one-line message of a non-signed tag should succeed' ' git tag -m "A msg" tag-one-line && echo "tag-one-line" >expect && @@ -819,8 +820,7 @@ test_expect_success 'The -n 100 invocation means -n --list 100, not -n100' ' test_cmp expect actual ' -test_expect_success \ - 'listing the zero-lines message of a non-signed tag should succeed' ' +test_expect_success 'listing the zero-lines message of a non-signed tag should succeed' ' git tag -m "" tag-zero-lines && echo "tag-zero-lines" >expect && @@ -844,11 +844,10 @@ test_expect_success \ test_cmp expect actual ' -echo 'tag line one' >annotagmsg -echo 'tag line two' >>annotagmsg -echo 'tag line three' >>annotagmsg -test_expect_success \ - 'listing many message lines of a non-signed tag should succeed' ' +test_expect_success 'listing many message lines of a non-signed tag should succeed' ' + echo "tag line one" >annotagmsg && + echo "tag line two" >>annotagmsg && + echo "tag line three" >>annotagmsg && git tag -F annotagmsg tag-lines && echo "tag-lines" >expect && @@ -936,40 +935,37 @@ test_expect_success 'git tag --format with ahead-behind' ' # trying to verify annotated non-signed tags: -test_expect_success GPG \ - 'trying to verify an annotated non-signed tag should fail' ' +test_expect_success GPG 'trying to verify an annotated non-signed tag should fail' ' tag_exists annotated-tag && test_must_fail git tag -v annotated-tag ' -test_expect_success GPG \ - 'trying to verify a file-annotated non-signed tag should fail' ' +test_expect_success GPG 'trying to verify a file-annotated non-signed tag should fail' ' tag_exists file-annotated-tag && test_must_fail git tag -v file-annotated-tag ' -test_expect_success GPG \ - 'trying to verify two annotated non-signed tags should fail' ' +test_expect_success GPG 'trying to verify two annotated non-signed tags should fail' ' tag_exists annotated-tag file-annotated-tag && test_must_fail git tag -v annotated-tag file-annotated-tag ' # creating and verifying signed tags: -get_tag_header signed-tag $commit commit $time >expect -echo 'A signed tag message' >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect test_expect_success GPG 'creating a signed tag with -m message should succeed' ' + get_tag_header signed-tag $commit commit $time >expect && + echo "A signed tag message" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "A signed tag message" signed-tag && get_tag_msg signed-tag >actual && test_cmp expect actual ' -get_tag_header u-signed-tag $commit commit $time >expect -echo 'Another message' >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect test_expect_success GPG 'sign with a given key id' ' + get_tag_header u-signed-tag $commit commit $time >expect && + echo "Another message" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -u committer@example.com -m "Another message" u-signed-tag && get_tag_msg u-signed-tag >actual && test_cmp expect actual @@ -989,137 +985,128 @@ test_expect_success GPG 'sign with an unknown id (2)' ' ' -cat >fakeeditor <<'EOF' -#!/bin/sh -test -n "$1" && exec >"$1" -echo A signed tag message -echo from a fake editor. -EOF -chmod +x fakeeditor - -get_tag_header implied-sign $commit commit $time >expect -./fakeeditor >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect test_expect_success GPG '-u implies signed tag' ' + write_script fakeeditor <<-\EOF && + test -n "$1" && exec >"$1" + echo A signed tag message + echo from a fake editor. + EOF + + get_tag_header implied-sign $commit commit $time >expect && + ./fakeeditor >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign && get_tag_msg implied-sign >actual && test_cmp expect actual ' -cat >sigmsgfile <<EOF -Another signed tag -message in a file. -EOF -get_tag_header file-signed-tag $commit commit $time >expect -cat sigmsgfile >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with -F messagefile should succeed' ' +test_expect_success GPG 'creating a signed tag with -F messagefile should succeed' ' + cat >sigmsgfile <<-\EOF && + Another signed tag + message in a file. + EOF + get_tag_header file-signed-tag $commit commit $time >expect && + cat sigmsgfile >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigmsgfile file-signed-tag && get_tag_msg file-signed-tag >actual && test_cmp expect actual ' -cat >siginputmsg <<EOF -A signed tag message from -the standard input -EOF -get_tag_header stdin-signed-tag $commit commit $time >expect -cat siginputmsg >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect test_expect_success GPG 'creating a signed tag with -F - should succeed' ' + cat >siginputmsg <<-\EOF && + A signed tag message from + the standard input + EOF + get_tag_header stdin-signed-tag $commit commit $time >expect && + cat siginputmsg >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F - stdin-signed-tag <siginputmsg && get_tag_msg stdin-signed-tag >actual && test_cmp expect actual ' -get_tag_header implied-annotate $commit commit $time >expect -./fakeeditor >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect test_expect_success GPG '-s implies annotated tag' ' + get_tag_header implied-annotate $commit commit $time >expect && + ./fakeeditor >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && GIT_EDITOR=./fakeeditor git tag -s implied-annotate && get_tag_msg implied-annotate >actual && test_cmp expect actual ' -get_tag_header forcesignannotated-implied-sign $commit commit $time >expect -echo "A message" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'git tag -s implied if configured with tag.forcesignannotated' \ - 'test_config tag.forcesignannotated true && +test_expect_success GPG 'git tag -s implied if configured with tag.forcesignannotated' ' + get_tag_header forcesignannotated-implied-sign $commit commit $time >expect && + echo "A message" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && + test_config tag.forcesignannotated true && git tag -m "A message" forcesignannotated-implied-sign && get_tag_msg forcesignannotated-implied-sign >actual && test_cmp expect actual ' -test_expect_success GPG \ - 'lightweight with no message when configured with tag.forcesignannotated' \ - 'test_config tag.forcesignannotated true && +test_expect_success GPG 'lightweight with no message when configured with tag.forcesignannotated' ' + test_config tag.forcesignannotated true && git tag forcesignannotated-lightweight && tag_exists forcesignannotated-lightweight && test_must_fail git tag -v forcesignannotated-no-message ' -get_tag_header forcesignannotated-annotate $commit commit $time >expect -echo "A message" >>expect -test_expect_success GPG \ - 'git tag -a disable configured tag.forcesignannotated' \ - 'test_config tag.forcesignannotated true && +test_expect_success GPG 'git tag -a disable configured tag.forcesignannotated' ' + get_tag_header forcesignannotated-annotate $commit commit $time >expect && + echo "A message" >>expect && + test_config tag.forcesignannotated true && git tag -a -m "A message" forcesignannotated-annotate && get_tag_msg forcesignannotated-annotate >actual && test_cmp expect actual && test_must_fail git tag -v forcesignannotated-annotate ' -get_tag_header forcesignannotated-disabled $commit commit $time >expect -echo "A message" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'git tag --sign enable GPG sign' \ - 'test_config tag.forcesignannotated false && +test_expect_success GPG 'git tag --sign enable GPG sign' ' + get_tag_header forcesignannotated-disabled $commit commit $time >expect && + echo "A message" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && + test_config tag.forcesignannotated false && git tag --sign -m "A message" forcesignannotated-disabled && get_tag_msg forcesignannotated-disabled >actual && test_cmp expect actual ' -get_tag_header gpgsign-enabled $commit commit $time >expect -echo "A message" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'git tag configured tag.gpgsign enables GPG sign' \ - 'test_config tag.gpgsign true && +test_expect_success GPG 'git tag configured tag.gpgsign enables GPG sign' ' + get_tag_header gpgsign-enabled $commit commit $time >expect && + echo "A message" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && + test_config tag.gpgsign true && git tag -m "A message" gpgsign-enabled && get_tag_msg gpgsign-enabled>actual && test_cmp expect actual ' -get_tag_header no-sign $commit commit $time >expect -echo "A message" >>expect -test_expect_success GPG \ - 'git tag --no-sign configured tag.gpgsign skip GPG sign' \ - 'test_config tag.gpgsign true && +test_expect_success GPG 'git tag --no-sign configured tag.gpgsign skip GPG sign' ' + get_tag_header no-sign $commit commit $time >expect && + echo "A message" >>expect && + test_config tag.gpgsign true && git tag -a --no-sign -m "A message" no-sign && get_tag_msg no-sign>actual && test_cmp expect actual ' -test_expect_success GPG \ - 'trying to create a signed tag with non-existing -F file should fail' ' +test_expect_success GPG 'trying to create a signed tag with non-existing -F file should fail' ' ! test -f nonexistingfile && ! tag_exists nosigtag && test_must_fail git tag -s -F nonexistingfile nosigtag && ! tag_exists nosigtag ' -test_expect_success GPG 'verifying a signed tag should succeed' \ - 'git tag -v signed-tag' +test_expect_success GPG 'verifying a signed tag should succeed' ' + git tag -v signed-tag +' -test_expect_success GPG 'verifying two signed tags in one command should succeed' \ - 'git tag -v signed-tag file-signed-tag' +test_expect_success GPG 'verifying two signed tags in one command should succeed' ' + git tag -v signed-tag file-signed-tag +' -test_expect_success GPG \ - 'verifying many signed and non-signed tags should fail' ' +test_expect_success GPG 'verifying many signed and non-signed tags should fail' ' test_must_fail git tag -v signed-tag annotated-tag && test_must_fail git tag -v file-annotated-tag file-signed-tag && test_must_fail git tag -v annotated-tag \ @@ -1150,78 +1137,72 @@ test_expect_success GPG 'verifying a forged tag with --format should fail silent # blank and empty messages for signed tags: -get_tag_header empty-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with an empty -m message should succeed' ' +test_expect_success GPG 'creating a signed tag with an empty -m message should succeed' ' + get_tag_header empty-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "" empty-signed-tag && get_tag_msg empty-signed-tag >actual && test_cmp expect actual && git tag -v empty-signed-tag ' ->sigemptyfile -get_tag_header emptyfile-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with an empty -F messagefile should succeed' ' +test_expect_success GPG 'creating a signed tag with an empty -F messagefile should succeed' ' + >sigemptyfile && + get_tag_header emptyfile-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigemptyfile emptyfile-signed-tag && get_tag_msg emptyfile-signed-tag >actual && test_cmp expect actual && git tag -v emptyfile-signed-tag ' -printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile -printf '\n\t \t \nRepeated blank lines\n' >>sigblanksfile -printf '\n\n\nTrailing spaces \t \n' >>sigblanksfile -printf '\nTrailing blank lines\n\n\t \n\n' >>sigblanksfile -get_tag_header blanks-signed-tag $commit commit $time >expect -cat >>expect <<EOF -Leading blank lines +test_expect_success GPG 'extra blanks in the message for a signed tag should be removed' ' + printf "\n\n \n\t\nLeading blank lines\n" >sigblanksfile && + printf "\n\t \t \nRepeated blank lines\n" >>sigblanksfile && + printf "\n\n\nTrailing spaces \t \n" >>sigblanksfile && + printf "\nTrailing blank lines\n\n\t \n\n" >>sigblanksfile && + get_tag_header blanks-signed-tag $commit commit $time >expect && + cat >>expect <<-\EOF && + Leading blank lines -Repeated blank lines + Repeated blank lines -Trailing spaces + Trailing spaces -Trailing blank lines -EOF -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'extra blanks in the message for a signed tag should be removed' ' + Trailing blank lines + EOF + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigblanksfile blanks-signed-tag && get_tag_msg blanks-signed-tag >actual && test_cmp expect actual && git tag -v blanks-signed-tag ' -get_tag_header blank-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with a blank -m message should succeed' ' +test_expect_success GPG 'creating a signed tag with a blank -m message should succeed' ' + get_tag_header blank-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m " " blank-signed-tag && get_tag_msg blank-signed-tag >actual && test_cmp expect actual && git tag -v blank-signed-tag ' -echo ' ' >sigblankfile -echo '' >>sigblankfile -echo ' ' >>sigblankfile -get_tag_header blankfile-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with blank -F file with spaces should succeed' ' +test_expect_success GPG 'creating a signed tag with blank -F file with spaces should succeed' ' + echo " " >sigblankfile && + echo "" >>sigblankfile && + echo " " >>sigblankfile && + get_tag_header blankfile-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigblankfile blankfile-signed-tag && get_tag_msg blankfile-signed-tag >actual && test_cmp expect actual && git tag -v blankfile-signed-tag ' -printf ' ' >sigblanknonlfile -get_tag_header blanknonlfile-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with spaces and no newline should succeed' ' +test_expect_success GPG 'creating a signed tag with spaces and no newline should succeed' ' + printf " " >sigblanknonlfile && + get_tag_header blanknonlfile-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigblanknonlfile blanknonlfile-signed-tag && get_tag_msg blanknonlfile-signed-tag >actual && test_cmp expect actual && @@ -1241,69 +1222,65 @@ test_expect_success GPG 'signed tag with embedded PGP message' ' # messages with commented lines for signed tags: -cat >sigcommentsfile <<EOF -# A comment +test_expect_success GPG 'creating a signed tag with a -F file with #comments should succeed' ' + cat >sigcommentsfile <<-\EOF && + # A comment -############ -The message. -############ -One line. + ############ + The message. + ############ + One line. -# commented lines -# commented lines + # commented lines + # commented lines -Another line. -# comments + Another line. + # comments -Last line. -EOF -get_tag_header comments-signed-tag $commit commit $time >expect -cat >>expect <<EOF -The message. -One line. + Last line. + EOF + get_tag_header comments-signed-tag $commit commit $time >expect && + cat >>expect <<-\EOF && + The message. + One line. -Another line. + Another line. -Last line. -EOF -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with a -F file with #comments should succeed' ' + Last line. + EOF + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigcommentsfile comments-signed-tag && get_tag_msg comments-signed-tag >actual && test_cmp expect actual && git tag -v comments-signed-tag ' -get_tag_header comment-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with #commented -m message should succeed' ' +test_expect_success GPG 'creating a signed tag with #commented -m message should succeed' ' + get_tag_header comment-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "#comment" comment-signed-tag && get_tag_msg comment-signed-tag >actual && test_cmp expect actual && git tag -v comment-signed-tag ' -echo '#comment' >sigcommentfile -echo '' >>sigcommentfile -echo '####' >>sigcommentfile -get_tag_header commentfile-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with #commented -F messagefile should succeed' ' +test_expect_success GPG 'creating a signed tag with #commented -F messagefile should succeed' ' + echo "#comment" >sigcommentfile && + echo "" >>sigcommentfile && + echo "####" >>sigcommentfile && + get_tag_header commentfile-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigcommentfile commentfile-signed-tag && get_tag_msg commentfile-signed-tag >actual && test_cmp expect actual && git tag -v commentfile-signed-tag ' -printf '#comment' >sigcommentnonlfile -get_tag_header commentnonlfile-signed-tag $commit commit $time >expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag with a #comment and no newline should succeed' ' +test_expect_success GPG 'creating a signed tag with a #comment and no newline should succeed' ' + printf "#comment" >sigcommentnonlfile && + get_tag_header commentnonlfile-signed-tag $commit commit $time >expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag && get_tag_msg commentnonlfile-signed-tag >actual && test_cmp expect actual && @@ -1312,8 +1289,7 @@ test_expect_success GPG \ # listing messages for signed tags: -test_expect_success GPG \ - 'listing the one-line message of a signed tag should succeed' ' +test_expect_success GPG 'listing the one-line message of a signed tag should succeed' ' git tag -s -m "A message line signed" stag-one-line && echo "stag-one-line" >expect && @@ -1337,8 +1313,7 @@ test_expect_success GPG \ test_cmp expect actual ' -test_expect_success GPG \ - 'listing the zero-lines message of a signed tag should succeed' ' +test_expect_success GPG 'listing the zero-lines message of a signed tag should succeed' ' git tag -s -m "" stag-zero-lines && echo "stag-zero-lines" >expect && @@ -1362,11 +1337,10 @@ test_expect_success GPG \ test_cmp expect actual ' -echo 'stag line one' >sigtagmsg -echo 'stag line two' >>sigtagmsg -echo 'stag line three' >>sigtagmsg -test_expect_success GPG \ - 'listing many message lines of a signed tag should succeed' ' +test_expect_success GPG 'listing many message lines of a signed tag should succeed' ' + echo "stag line one" >sigtagmsg && + echo "stag line two" >>sigtagmsg && + echo "stag line three" >>sigtagmsg && git tag -s -F sigtagmsg stag-lines && echo "stag-lines" >expect && @@ -1408,74 +1382,64 @@ test_expect_success GPG \ # tags pointing to objects different from commits: -tree=$(git rev-parse HEAD^{tree}) -blob=$(git rev-parse HEAD:foo) -tag=$(git rev-parse signed-tag 2>/dev/null) - -get_tag_header tree-signed-tag $tree tree $time >expect -echo "A message for a tree" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag pointing to a tree should succeed' ' +test_expect_success GPG 'creating a signed tag pointing to a tree should succeed' ' + tree=$(git rev-parse HEAD^{tree}) && + get_tag_header tree-signed-tag $tree tree $time >expect && + echo "A message for a tree" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} && get_tag_msg tree-signed-tag >actual && test_cmp expect actual ' -get_tag_header blob-signed-tag $blob blob $time >expect -echo "A message for a blob" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag pointing to a blob should succeed' ' +test_expect_success GPG 'creating a signed tag pointing to a blob should succeed' ' + blob=$(git rev-parse HEAD:foo) && + get_tag_header blob-signed-tag $blob blob $time >expect && + echo "A message for a blob" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo && get_tag_msg blob-signed-tag >actual && test_cmp expect actual ' -get_tag_header tag-signed-tag $tag tag $time >expect -echo "A message for another tag" >>expect -echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success GPG \ - 'creating a signed tag pointing to another tag should succeed' ' +test_expect_success GPG 'creating a signed tag pointing to another tag should succeed' ' + tag=$(git rev-parse signed-tag 2>/dev/null) && + get_tag_header tag-signed-tag $tag tag $time >expect && + echo "A message for another tag" >>expect && + echo "-----BEGIN PGP SIGNATURE-----" >>expect && git tag -s -m "A message for another tag" tag-signed-tag signed-tag && get_tag_msg tag-signed-tag >actual && test_cmp expect actual ' # usage with rfc1991 signatures -get_tag_header rfc1991-signed-tag $commit commit $time >expect -echo "RFC1991 signed tag" >>expect -echo '-----BEGIN PGP MESSAGE-----' >>expect -test_expect_success GPG,RFC1991 \ - 'creating a signed tag with rfc1991' ' + +test_expect_success GPG,RFC1991 'creating a signed tag with rfc1991' ' + get_tag_header rfc1991-signed-tag $commit commit $time >expect && + echo "RFC1991 signed tag" >>expect && + echo "-----BEGIN PGP MESSAGE-----" >>expect && echo "rfc1991" >gpghome/gpg.conf && git tag -s -m "RFC1991 signed tag" rfc1991-signed-tag $commit && get_tag_msg rfc1991-signed-tag >actual && test_cmp expect actual ' -cat >fakeeditor <<'EOF' -#!/bin/sh -cp "$1" actual -EOF -chmod +x fakeeditor - -test_expect_success GPG,RFC1991 \ - 'reediting a signed tag body omits signature' ' +test_expect_success GPG,RFC1991 'reediting a signed tag body omits signature' ' + write_script fakeeditor <<-\EOF && + cp "$1" actual + EOF echo "rfc1991" >gpghome/gpg.conf && echo "RFC1991 signed tag" >expect && GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit && test_cmp expect actual ' -test_expect_success GPG,RFC1991 \ - 'verifying rfc1991 signature' ' +test_expect_success GPG,RFC1991 'verifying rfc1991 signature' ' echo "rfc1991" >gpghome/gpg.conf && git tag -v rfc1991-signed-tag ' -test_expect_success GPG,RFC1991 \ - 'list tag with rfc1991 signature' ' +test_expect_success GPG,RFC1991 'list tag with rfc1991 signature' ' echo "rfc1991" >gpghome/gpg.conf && echo "rfc1991-signed-tag RFC1991 signed tag" >expect && git tag -l -n1 rfc1991-signed-tag >actual && @@ -1486,15 +1450,12 @@ test_expect_success GPG,RFC1991 \ test_cmp expect actual ' -rm -f gpghome/gpg.conf - -test_expect_success GPG,RFC1991 \ - 'verifying rfc1991 signature without --rfc1991' ' +test_expect_success GPG,RFC1991 'verifying rfc1991 signature without --rfc1991' ' + rm -f gpghome/gpg.conf && git tag -v rfc1991-signed-tag ' -test_expect_success GPG,RFC1991 \ - 'list tag with rfc1991 signature without --rfc1991' ' +test_expect_success GPG,RFC1991 'list tag with rfc1991 signature without --rfc1991' ' echo "rfc1991-signed-tag RFC1991 signed tag" >expect && git tag -l -n1 rfc1991-signed-tag >actual && test_cmp expect actual && @@ -1504,24 +1465,23 @@ test_expect_success GPG,RFC1991 \ test_cmp expect actual ' -test_expect_success GPG,RFC1991 \ - 'reediting a signed tag body omits signature' ' +test_expect_success GPG,RFC1991 'reediting a signed tag body omits signature' ' echo "RFC1991 signed tag" >expect && GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit && test_cmp expect actual ' # try to sign with bad user.signingkey -test_expect_success GPG \ - 'git tag -s fails if gpg is misconfigured (bad key)' \ - 'test_config user.signingkey BobTheMouse && - test_must_fail git tag -s -m tail tag-gpg-failure' +test_expect_success GPG 'git tag -s fails if gpg is misconfigured (bad key)' ' + test_config user.signingkey BobTheMouse && + test_must_fail git tag -s -m tail tag-gpg-failure +' # try to produce invalid signature -test_expect_success GPG \ - 'git tag -s fails if gpg is misconfigured (bad signature format)' \ - 'test_config gpg.program echo && - test_must_fail git tag -s -m tail tag-gpg-failure' +test_expect_success GPG 'git tag -s fails if gpg is misconfigured (bad signature format)' ' + test_config gpg.program echo && + test_must_fail git tag -s -m tail tag-gpg-failure +' # try to produce invalid signature test_expect_success GPG 'git verifies tag is valid with double signature' ' @@ -1542,34 +1502,32 @@ test_expect_success GPG 'git verifies tag is valid with double signature' ' ' # try to sign with bad user.signingkey -test_expect_success GPGSM \ - 'git tag -s fails if gpgsm is misconfigured (bad key)' \ - 'test_config user.signingkey BobTheMouse && - test_config gpg.format x509 && - test_must_fail git tag -s -m tail tag-gpg-failure' +test_expect_success GPGSM 'git tag -s fails if gpgsm is misconfigured (bad key)' ' + test_config user.signingkey BobTheMouse && + test_config gpg.format x509 && + test_must_fail git tag -s -m tail tag-gpg-failure +' # try to produce invalid signature -test_expect_success GPGSM \ - 'git tag -s fails if gpgsm is misconfigured (bad signature format)' \ - 'test_config gpg.x509.program echo && - test_config gpg.format x509 && - test_must_fail git tag -s -m tail tag-gpg-failure' +test_expect_success GPGSM 'git tag -s fails if gpgsm is misconfigured (bad signature format)' ' + test_config gpg.x509.program echo && + test_config gpg.format x509 && + test_must_fail git tag -s -m tail tag-gpg-failure +' # try to verify without gpg: -rm -rf gpghome -test_expect_success GPG \ - 'verify signed tag fails when public key is not present' \ - 'test_must_fail git tag -v signed-tag' +test_expect_success GPG 'verify signed tag fails when public key is not present' ' + rm -rf gpghome && + test_must_fail git tag -v signed-tag +' -test_expect_success \ - 'git tag -a fails if tag annotation is empty' ' +test_expect_success 'git tag -a fails if tag annotation is empty' ' ! (GIT_EDITOR=cat git tag -a initial-comment) ' -test_expect_success \ - 'message in editor has initial comment' ' - ! (GIT_EDITOR=cat git tag -a initial-comment > actual) +test_expect_success 'message in editor has initial comment' ' + ! (GIT_EDITOR=cat git tag -a initial-comment >actual) ' test_expect_success 'message in editor has initial comment: first line' ' @@ -1579,17 +1537,15 @@ test_expect_success 'message in editor has initial comment: first line' ' test_cmp first.expect first.actual ' -test_expect_success \ - 'message in editor has initial comment: remainder' ' +test_expect_success 'message in editor has initial comment: remainder' ' # remove commented lines from the remainder -- should be empty sed -e 1d -e "/^#/d" <actual >rest.actual && test_must_be_empty rest.actual ' -get_tag_header reuse $commit commit $time >expect -echo "An annotation to be reused" >> expect -test_expect_success \ - 'overwriting an annotated tag should use its previous body' ' +test_expect_success 'overwriting an annotated tag should use its previous body' ' + get_tag_header reuse $commit commit $time >expect && + echo "An annotation to be reused" >>expect && git tag -a -m "An annotation to be reused" reuse && GIT_EDITOR=true git tag -f -a reuse && get_tag_msg reuse >actual && @@ -1618,192 +1574,202 @@ test_expect_success 'filename for the message is relative to cwd' ' # create a few more commits to test --contains -hash1=$(git rev-parse HEAD) - test_expect_success 'creating second commit and tag' ' + hash1=$(git rev-parse HEAD) && echo foo-2.0 >foo && git add foo && git commit -m second && git tag v2.0 ' -hash2=$(git rev-parse HEAD) - test_expect_success 'creating third commit without tag' ' + hash2=$(git rev-parse HEAD) && echo foo-dev >foo && git add foo && git commit -m third ' -hash3=$(git rev-parse HEAD) - # simple linear checks of --continue -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -v2.0 -EOF - -test_expect_success 'checking that first commit is in all tags (hash)' " +test_expect_success 'checking that first commit is in all tags (hash)' ' + hash3=$(git rev-parse HEAD) && + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + EOF git tag -l --contains $hash1 v* >actual && test_cmp expected actual -" +' # other ways of specifying the commit -test_expect_success 'checking that first commit is in all tags (tag)' " +test_expect_success 'checking that first commit is in all tags (tag)' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + EOF git tag -l --contains v1.0 v* >actual && test_cmp expected actual -" +' -test_expect_success 'checking that first commit is in all tags (relative)' " +test_expect_success 'checking that first commit is in all tags (relative)' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + EOF git tag -l --contains HEAD~2 v* >actual && test_cmp expected actual -" +' # All the --contains tests above, but with --no-contains -test_expect_success 'checking that first commit is not listed in any tag with --no-contains (hash)' " +test_expect_success 'checking that first commit is not listed in any tag with --no-contains (hash)' ' git tag -l --no-contains $hash1 v* >actual && test_must_be_empty actual -" +' -test_expect_success 'checking that first commit is in all tags (tag)' " +test_expect_success 'checking that first commit is in all tags (tag)' ' git tag -l --no-contains v1.0 v* >actual && test_must_be_empty actual -" +' -test_expect_success 'checking that first commit is in all tags (relative)' " +test_expect_success 'checking that first commit is in all tags (relative)' ' git tag -l --no-contains HEAD~2 v* >actual && test_must_be_empty actual -" - -cat > expected <<EOF -v2.0 -EOF +' -test_expect_success 'checking that second commit only has one tag' " +test_expect_success 'checking that second commit only has one tag' ' + cat >expected <<-\EOF && + v2.0 + EOF git tag -l --contains $hash2 v* >actual && test_cmp expected actual -" - -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -EOF +' -test_expect_success 'inverse of the last test, with --no-contains' " +test_expect_success 'inverse of the last test, with --no-contains' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + EOF git tag -l --no-contains $hash2 v* >actual && test_cmp expected actual -" +' -test_expect_success 'checking that third commit has no tags' " +test_expect_success 'checking that third commit has no tags' ' git tag -l --contains $hash3 v* >actual && test_must_be_empty actual -" - -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -v2.0 -EOF +' -test_expect_success 'conversely --no-contains on the third commit lists all tags' " +test_expect_success 'conversely --no-contains on the third commit lists all tags' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + EOF git tag -l --no-contains $hash3 v* >actual && test_cmp expected actual -" +' # how about a simple merge? test_expect_success 'creating simple branch' ' git branch stable v2.0 && git checkout stable && - echo foo-3.0 > foo && + echo foo-3.0 >foo && git commit foo -m fourth && git tag v3.0 ' -hash4=$(git rev-parse HEAD) - -cat > expected <<EOF -v3.0 -EOF - -test_expect_success 'checking that branch head only has one tag' " +test_expect_success 'checking that branch head only has one tag' ' + hash4=$(git rev-parse HEAD) && + cat >expected <<-\EOF && + v3.0 + EOF git tag -l --contains $hash4 v* >actual && test_cmp expected actual -" - -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -v2.0 -EOF +' -test_expect_success 'checking that branch head with --no-contains lists all but one tag' " +test_expect_success 'checking that branch head with --no-contains lists all but one tag' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + EOF git tag -l --no-contains $hash4 v* >actual && test_cmp expected actual -" +' test_expect_success 'merging original branch into this branch' ' git merge --strategy=ours main && git tag v4.0 ' -cat > expected <<EOF -v4.0 -EOF - -test_expect_success 'checking that original branch head has one tag now' " +test_expect_success 'checking that original branch head has one tag now' ' + cat >expected <<-\EOF && + v4.0 + EOF git tag -l --contains $hash3 v* >actual && test_cmp expected actual -" - -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -v2.0 -v3.0 -EOF +' -test_expect_success 'checking that original branch head with --no-contains lists all but one tag now' " +test_expect_success 'checking that original branch head with --no-contains lists all but one tag now' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + v3.0 + EOF git tag -l --no-contains $hash3 v* >actual && test_cmp expected actual -" - -cat > expected <<EOF -v0.2.1 -v1.0 -v1.0.1 -v1.1.3 -v2.0 -v3.0 -v4.0 -EOF +' -test_expect_success 'checking that initial commit is in all tags' " +test_expect_success 'checking that initial commit is in all tags' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + v3.0 + v4.0 + EOF git tag -l --contains $hash1 v* >actual && test_cmp expected actual -" +' test_expect_success 'checking that --contains can be used in non-list mode' ' + cat >expected <<-\EOF && + v0.2.1 + v1.0 + v1.0.1 + v1.1.3 + v2.0 + v3.0 + v4.0 + EOF git tag --contains $hash1 v* >actual && test_cmp expected actual ' -test_expect_success 'checking that initial commit is in all tags with --no-contains' " +test_expect_success 'checking that initial commit is in all tags with --no-contains' ' git tag -l --no-contains $hash1 v* >actual && test_must_be_empty actual -" +' # mixing modes and options: @@ -1840,16 +1806,16 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' for option in --contains --with --no-contains --without --merged --no-merged --points-at do - test_expect_success "mixing incompatible modes with $option is forbidden" " + test_expect_success "mixing incompatible modes with $option is forbidden" ' test_must_fail git tag -d $option HEAD && test_must_fail git tag -d $option HEAD some-tag && test_must_fail git tag -v $option HEAD - " - test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" " + ' + test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" ' git tag -n $option HEAD HEAD && git tag $option HEAD HEAD && git tag $option - " + ' done # check points-at @@ -1896,7 +1862,7 @@ test_expect_success 'recursive tagging should give advice' ' hint: already a tag. If you meant to tag the object that it points to, use: hint: hint: git tag -f nested annotated-v4.0^{} - hint: Disable this message with "git config advice.nestedTag false" + hint: Disable this message with "git config set advice.nestedTag false" EOF git tag -m nested nested annotated-v4.0 2>actual && test_cmp expect actual @@ -2225,7 +2191,7 @@ test_expect_success 'git tag -l with --format="%(rest)" must fail' ' test_must_fail git tag -l --format="%(rest)" "v1*" ' -test_expect_success "set up color tests" ' +test_expect_success 'set up color tests' ' echo "<RED>v1.0<RESET>" >expect.color && echo "v1.0" >expect.bare && color_args="--format=%(color:red)%(refname:short) --list v1.0" diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index b9822294fe..5fcf281dfb 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -2,7 +2,6 @@ test_description='GIT_EDITOR, core.editor, and stuff' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh unset EDITOR VISUAL GIT_EDITOR diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index a0296d6ca4..932c26cb45 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -2,7 +2,6 @@ test_description='Test automatic use of a pager.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pager.sh . "$TEST_DIRECTORY"/lib-terminal.sh diff --git a/t/t7007-show.sh b/t/t7007-show.sh index f908a4d1ab..d6cc69e0f2 100755 --- a/t/t7007-show.sh +++ b/t/t7007-show.sh @@ -2,7 +2,6 @@ test_description='git show' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh index d9add2162e..520f96d09f 100755 --- a/t/t7010-setup.sh +++ b/t/t7010-setup.sh @@ -2,7 +2,6 @@ test_description='setup taking and sanitizing funny paths' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh index 4adac5acd5..1ff2714cb4 100755 --- a/t/t7011-skip-worktree-reading.sh +++ b/t/t7011-skip-worktree-reading.sh @@ -5,7 +5,6 @@ test_description='skip-worktree bit test' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expect.full <<EOF @@ -32,24 +31,24 @@ setup_absent() { } test_absent() { - echo "100644 $EMPTY_BLOB 0 1" > expected && - git ls-files --stage 1 > result && + echo "100644 $EMPTY_BLOB 0 1" >expected && + git ls-files --stage 1 >result && test_cmp expected result && test ! -f 1 } setup_dirty() { git update-index --force-remove 1 && - echo dirty > 1 && + echo dirty >1 && git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 && git update-index --skip-worktree 1 } test_dirty() { - echo "100644 $EMPTY_BLOB 0 1" > expected && - git ls-files --stage 1 > result && + echo "100644 $EMPTY_BLOB 0 1" >expected && + git ls-files --stage 1 >result && test_cmp expected result && - echo dirty > expected + echo dirty >expected test_cmp expected 1 } @@ -59,7 +58,7 @@ test_expect_success 'setup' ' touch ./1 ./2 sub/1 sub/2 && git add 1 2 sub/1 sub/2 && git update-index --skip-worktree 1 sub/1 && - git ls-files -t > result && + git ls-files -t >result && test_cmp expect.skip result ' @@ -86,7 +85,7 @@ test_expect_success 'update-index --remove' ' setup_dirty && git update-index --remove 1 && test -z "$(git ls-files 1)" && - echo dirty > expected && + echo dirty >expected && test_cmp expected 1 ' @@ -110,16 +109,16 @@ test_expect_success 'ls-files --modified' ' test -z "$(git ls-files -m)" ' -echo ":000000 100644 $ZERO_OID $EMPTY_BLOB A 1" > expected +echo ":000000 100644 $ZERO_OID $EMPTY_BLOB A 1" >expected test_expect_success 'diff-index does not examine skip-worktree absent entries' ' setup_absent && - git diff-index HEAD -- 1 > result && + git diff-index HEAD -- 1 >result && test_cmp expected result ' test_expect_success 'diff-index does not examine skip-worktree dirty entries' ' setup_dirty && - git diff-index HEAD -- 1 > result && + git diff-index HEAD -- 1 >result && test_cmp expected result ' diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh index d984200c17..cd5c20fe51 100755 --- a/t/t7012-skip-worktree-writing.sh +++ b/t/t7012-skip-worktree-writing.sh @@ -5,7 +5,6 @@ test_description='test worktree writing operations when skip-worktree is used' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh index 20913b3713..80359d48f7 100755 --- a/t/t7031-verify-tag-signed-ssh.sh +++ b/t/t7031-verify-tag-signed-ssh.sh @@ -116,7 +116,7 @@ test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag succeeds with tag date ! grep "${GPGSSH_BAD_SIGNATURE}" actual ' -test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag failes with tag date outside of key validity' ' +test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag fails with tag date outside of key validity' ' test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" && test_must_fail git verify-tag timeboxedinvalid-signed 2>actual && ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index aaeb4a5334..0f4344c55e 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -5,7 +5,6 @@ test_description='basic work tree status reporting' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7062-wtstatus-ignorecase.sh b/t/t7062-wtstatus-ignorecase.sh index caf372a3d4..73709dbeee 100755 --- a/t/t7062-wtstatus-ignorecase.sh +++ b/t/t7062-wtstatus-ignorecase.sh @@ -2,7 +2,6 @@ test_description='git-status with core.ignorecase=true' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'status with hash collisions' ' diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh index 06c1301222..8bbc5ce6d9 100755 --- a/t/t7064-wtstatus-pv2.sh +++ b/t/t7064-wtstatus-pv2.sh @@ -4,7 +4,6 @@ test_description='git status --porcelain=v2 This test exercises porcelain V2 output for git status.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh @@ -77,7 +76,7 @@ test_expect_success 'before initial commit, things added (-z)' ' test_cmp expect actual ' -test_expect_success 'make first commit, comfirm HEAD oid and branch' ' +test_expect_success 'make first commit, confirm HEAD oid and branch' ' git commit -m initial && H0=$(git rev-parse HEAD) && cat >expect <<-EOF && diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh index 89cf98b30c..33d5d5b76e 100755 --- a/t/t7101-reset-empty-subdirs.sh +++ b/t/t7101-reset-empty-subdirs.sh @@ -5,7 +5,6 @@ test_description='git reset should cull empty subdirs' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-data.sh diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 2add26d768..0503a64d3f 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -10,24 +10,33 @@ Documented tests for git reset' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -commit_msg () { - # String "modify 2nd file (changed)" partly in German - # (translated with Google Translate), - # encoded in UTF-8, used as a commit log message below. - msg="modify 2nd file (ge\303\244ndert)\n" - if test -n "$1" - then - printf "$msg" | iconv -f utf-8 -t "$1" - else - printf "$msg" - fi -} - -# Tested non-UTF-8 encoding -test_encoding="ISO8859-1" +if test_have_prereq ICONV +then + commit_msg () { + # String "modify 2nd file (changed)" partly in German + # (translated with Google Translate), + # encoded in UTF-8, used as a commit log message below. + msg="modify 2nd file (ge\303\244ndert)\n" + if test -n "$1" + then + printf "$msg" | iconv -f utf-8 -t "$1" + else + printf "$msg" + fi + } + + # Tested non-UTF-8 encoding + test_encoding="ISO8859-1" +else + commit_msg () { + echo "modify 2nd file (geandert)" + } + + # Tested non-UTF-8 encoding + test_encoding="UTF-8" +fi test_expect_success 'creating initial files and commits' ' test_tick && diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh index 18bbd9975e..871e438118 100755 --- a/t/t7103-reset-bare.sh +++ b/t/t7103-reset-bare.sh @@ -2,7 +2,6 @@ test_description='git reset in a bare repository' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup non-bare' ' diff --git a/t/t7104-reset-hard.sh b/t/t7104-reset-hard.sh index cf9697eba9..7948ec392b 100755 --- a/t/t7104-reset-hard.sh +++ b/t/t7104-reset-hard.sh @@ -2,7 +2,6 @@ test_description='reset --hard unmerged' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh index f4f3b7a677..fced8adabd 100755 --- a/t/t7105-reset-patch.sh +++ b/t/t7105-reset-patch.sh @@ -2,7 +2,6 @@ test_description='git reset --patch' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh test_expect_success 'setup' ' diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh index 88d1c8adf4..df20c0f0cc 100755 --- a/t/t7106-reset-unborn-branch.sh +++ b/t/t7106-reset-unborn-branch.sh @@ -2,7 +2,6 @@ test_description='git reset should work on unborn branch' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh index 020db201d5..9162f591fb 100755 --- a/t/t7107-reset-pathspec-file.sh +++ b/t/t7107-reset-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='reset --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh index 7ee180f81d..61669a2d21 100755 --- a/t/t7110-reset-merge.sh +++ b/t/t7110-reset-merge.sh @@ -5,7 +5,6 @@ test_description='Tests for "git reset" with "--merge" and "--keep" options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh index 01b7c3503c..07b919731a 100755 --- a/t/t7111-reset-table.sh +++ b/t/t7111-reset-table.sh @@ -5,7 +5,6 @@ test_description='Tests to check that "reset" options follow a known table' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh index b0d3d93b0b..a3e2413bc3 100755 --- a/t/t7112-reset-submodule.sh +++ b/t/t7112-reset-submodule.sh @@ -2,7 +2,6 @@ test_description='reset can handle submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh diff --git a/t/t7113-post-index-change-hook.sh b/t/t7113-post-index-change-hook.sh index 58e55a7c77..c10d94fe3d 100755 --- a/t/t7113-post-index-change-hook.sh +++ b/t/t7113-post-index-change-hook.sh @@ -5,7 +5,6 @@ test_description='post index change hook' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 189d8e341b..9bcf7c0b40 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -23,7 +23,6 @@ Test switching across them. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick @@ -225,7 +224,7 @@ test_expect_success 'switch to another branch while carrying a deletion' ' ' test_expect_success 'checkout to detach HEAD (with advice declined)' ' - git config advice.detachedHead false && + git config set advice.detachedHead false && rev=$(git rev-parse --short renamer^) && git checkout -f renamer && git clean -f && @@ -245,7 +244,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' ' ' test_expect_success 'checkout to detach HEAD' ' - git config advice.detachedHead true && + git config set advice.detachedHead true && rev=$(git rev-parse --short renamer^) && git checkout -f renamer && git clean -f && @@ -498,6 +497,19 @@ test_expect_success 'checkout unmerged stage' ' test ztheirside = "z$(cat file)" ' +test_expect_success 'checkout --ours is incompatible with switching' ' + test_must_fail git checkout --ours 2>error && + test_grep "needs the paths to check out" error && + + test_must_fail git checkout --ours HEAD 2>error && + test_grep "cannot be used with switching" error && + + test_must_fail git checkout --ours main 2>error && + test_grep "cannot be used with switching" error && + + git checkout --ours file +' + test_expect_success 'checkout path with --merge from tree-ish is a no-no' ' setup_conflicting_index && test_must_fail git checkout -m HEAD -- file diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 0aae0dee67..00d4070156 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -5,7 +5,6 @@ test_description='git clean basic tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh git config clean.requireForce no @@ -29,15 +28,15 @@ test_expect_success 'git clean with skip-worktree .gitignore' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so && + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so && git update-index --no-skip-worktree .gitignore && git checkout .gitignore ' @@ -47,15 +46,15 @@ test_expect_success 'git clean' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -64,15 +63,15 @@ test_expect_success 'git clean src/' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean src/ && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -81,15 +80,15 @@ test_expect_success 'git clean src/ src/' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean src/ src/ && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -98,16 +97,16 @@ test_expect_success 'git clean with prefix' ' mkdir -p build docs src/test && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c && (cd src/ && git clean) && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f src/part3.c && - test -f src/test/1.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_missing src/part3.c && + test_path_is_file src/test/1.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -163,16 +162,16 @@ test_expect_success 'git clean -d with prefix and path' ' mkdir -p build docs src/feature && touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so && (cd src/ && git clean -d feature/) && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f src/part3.c && - test ! -f src/feature/file.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_file src/part3.c && + test_path_is_missing src/feature/file.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -182,16 +181,16 @@ test_expect_success SYMLINKS 'git clean symbolic link' ' touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && ln -s docs/manual.txt src/part4.c && git clean && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test ! -f src/part4.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_missing src/part4.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -199,13 +198,13 @@ test_expect_success 'git clean with wildcard' ' touch a.clean b.clean other.c && git clean "*.clean" && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.clean && - test ! -f b.clean && - test -f other.c + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.clean && + test_path_is_missing b.clean && + test_path_is_file other.c ' @@ -214,15 +213,15 @@ test_expect_success 'git clean -n' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -n && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_file src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -231,15 +230,15 @@ test_expect_success 'git clean -d' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test ! -d docs && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_missing docs && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -248,16 +247,16 @@ test_expect_success 'git clean -d src/ examples/' ' mkdir -p build docs examples && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c && git clean -d src/ examples/ && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f src/part3.c && - test ! -f examples/1.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_missing src/part3.c && + test_path_is_missing examples/1.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -266,15 +265,15 @@ test_expect_success 'git clean -x' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -x && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test ! -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_missing obj.o && + test_path_is_file build/lib.so ' @@ -283,15 +282,15 @@ test_expect_success 'git clean -d -x' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -x && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test ! -d docs && - test ! -f obj.o && - test ! -d build + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_missing docs && + test_path_is_missing obj.o && + test_path_is_missing build ' @@ -300,15 +299,15 @@ test_expect_success 'git clean -d -x with ignored tracked directory' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -x -e src && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f src/part3.c && - test ! -d docs && - test ! -f obj.o && - test ! -d build + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_file src/part3.c && + test_path_is_missing docs && + test_path_is_missing obj.o && + test_path_is_missing build ' @@ -317,15 +316,15 @@ test_expect_success 'git clean -X' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -X && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f src/part3.c && - test -f docs/manual.txt && - test ! -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_file src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_missing obj.o && + test_path_is_file build/lib.so ' @@ -334,15 +333,15 @@ test_expect_success 'git clean -d -X' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -X && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f src/part3.c && - test -f docs/manual.txt && - test ! -f obj.o && - test ! -d build + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_file src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_missing obj.o && + test_path_is_missing build ' @@ -351,15 +350,15 @@ test_expect_success 'git clean -d -X with ignored tracked directory' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -d -X -e src && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test ! -f obj.o && - test ! -d build + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_missing obj.o && + test_path_is_missing build ' @@ -382,29 +381,29 @@ test_expect_success 'clean.requireForce and -n' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && git clean -n && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file Makefile && + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_file a.out && + test_path_is_file src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' test_expect_success 'clean.requireForce and -f' ' git clean -f && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f src/part3.c && - test -f docs/manual.txt && - test -f obj.o && - test -f build/lib.so + test_path_is_file README && + test_path_is_file src/part1.c && + test_path_is_file src/part2.c && + test_path_is_missing a.out && + test_path_is_missing src/part3.c && + test_path_is_file docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -453,11 +452,11 @@ test_expect_success 'nested git work tree' ' test_commit deeply.nested deeper.world ) && git clean -f -d && - test -f foo/.git/index && - test -f foo/hello.world && - test -f baz/boo/.git/index && - test -f baz/boo/deeper.world && - ! test -d bar + test_path_is_file foo/.git/index && + test_path_is_file foo/hello.world && + test_path_is_file baz/boo/.git/index && + test_path_is_file baz/boo/deeper.world && + test_path_is_missing bar ' test_expect_success 'should clean things that almost look like git but are not' ' @@ -624,9 +623,9 @@ test_expect_success 'force removal of nested git work tree' ' test_commit deeply.nested deeper.world ) && git clean -f -f -d && - ! test -d foo && - ! test -d bar && - ! test -d baz + test_path_is_missing foo && + test_path_is_missing bar && + test_path_is_missing baz ' test_expect_success 'git clean -e' ' @@ -638,10 +637,10 @@ test_expect_success 'git clean -e' ' touch known 1 2 3 && git add known && git clean -f -e 1 -e 2 && - test -e 1 && - test -e 2 && - ! (test -e 3) && - test -e known + test_path_exists 1 && + test_path_exists 2 && + test_path_is_missing 3 && + test_path_exists known ) ' @@ -649,7 +648,7 @@ test_expect_success SANITY 'git clean -d with an unreadable empty directory' ' mkdir foo && chmod a= foo && git clean -dfx foo && - ! test -d foo + test_path_is_missing foo ' test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' ' @@ -747,7 +746,7 @@ test_expect_success MINGW 'handle clean & core.longpaths = false nicely' ' test_must_fail git clean -xdf 2>.git/err && # grepping for a strerror string is unportable but it is OK here with # MINGW prereq - test_grep "too long" .git/err + test_grep -e "too long" -e "No such file or directory" .git/err ' test_expect_success 'clean untracked paths by pathspec' ' diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh index 4afe53c66a..f743e5b8f4 100755 --- a/t/t7301-clean-interactive.sh +++ b/t/t7301-clean-interactive.sh @@ -2,7 +2,6 @@ test_description='git clean -i basic tests' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 098d8833b6..d6a501d453 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -12,7 +12,6 @@ subcommands of git submodule. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup - enable local submodules' ' @@ -213,7 +212,7 @@ test_expect_success 'submodule add to .gitignored path fails' ' The following paths are ignored by one of your .gitignore files: submod hint: Use -f if you really want to add them. - hint: Disable this message with "git config advice.addIgnoredFile false" + hint: Disable this message with "git config set advice.addIgnoredFile false" EOF # Does not use test_commit due to the ignore echo "*" > .gitignore && diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index 542b3331a7..9c3cc4cf40 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -17,7 +17,6 @@ This test script tries to verify the sanity of summary subcommand of git submodu # various reasons, one of them being that there are lots of commands taking place # outside of 'test_expect_success' block, which is no longer in good-style. -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh add_file () { diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index aa2fdc31d1..25b33a1e87 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -5,7 +5,6 @@ test_description='Test rebasing, stashing, etc. with submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 19b6135d11..bf97d4f851 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -11,7 +11,6 @@ These tests exercise the "git submodule sync" subcommand. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index d6040e0a33..f860e7bbf4 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -4,6 +4,7 @@ # test_description='test clone --reference' + . ./test-lib.sh base_dir=$(pwd) diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh index 574a6fc526..374ed481e9 100755 --- a/t/t7409-submodule-detached-work-tree.sh +++ b/t/t7409-submodule-detached-work-tree.sh @@ -13,7 +13,6 @@ TEST_NO_CREATE_REPO=1 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh index f778321857..0490499573 100755 --- a/t/t7412-submodule-absorbgitdirs.sh +++ b/t/t7412-submodule-absorbgitdirs.sh @@ -6,7 +6,6 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git directory into the superproject. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup a real submodule' ' diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh index 887d181b72..9509dc18fd 100755 --- a/t/t7413-submodule-is-active.sh +++ b/t/t7413-submodule-is-active.sh @@ -9,7 +9,6 @@ This is a unit test of the submodule.c is_submodule_active() function, which is also indirectly tested elsewhere. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -22,7 +21,7 @@ test_expect_success 'setup' ' git -C super submodule add ../sub sub2 && # Remove submodule.<name>.active entries in order to test in an - # environment where only URLs are present in the conifg + # environment where only URLs are present in the config git -C super config --unset submodule.sub1.active && git -C super config --unset submodule.sub2.active && diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh index 24f30e3bf9..e2d75c7f16 100755 --- a/t/t7414-submodule-mistakes.sh +++ b/t/t7414-submodule-mistakes.sh @@ -2,7 +2,6 @@ test_description='handling of common mistakes people may make with submodules' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create embedded repository' ' diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh index 2ab566e717..0c605fd271 100755 --- a/t/t7416-submodule-dash-url.sh +++ b/t/t7416-submodule-dash-url.sh @@ -2,7 +2,6 @@ test_description='check handling of disallowed .gitmodule urls' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7417-submodule-path-url.sh b/t/t7417-submodule-path-url.sh index dbbb3853dc..5e3051da8b 100755 --- a/t/t7417-submodule-path-url.sh +++ b/t/t7417-submodule-path-url.sh @@ -4,7 +4,6 @@ test_description='check handling of .gitmodule path with dash' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh index a5d1bc5c54..08ed51d34f 100755 --- a/t/t7419-submodule-set-branch.sh +++ b/t/t7419-submodule-set-branch.sh @@ -9,7 +9,6 @@ This test verifies that the set-branch subcommand of git-submodule is working as expected. ' -TEST_PASSES_SANITIZE_LEAK=true TEST_NO_CREATE_REPO=1 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main diff --git a/t/t7421-submodule-summary-add.sh b/t/t7421-submodule-summary-add.sh index 479c8fdde1..ce64d8b137 100755 --- a/t/t7421-submodule-summary-add.sh +++ b/t/t7421-submodule-summary-add.sh @@ -10,7 +10,6 @@ while making sure to add submodules using `git submodule add` instead of `git add` as done in t7401. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh index ab946ec940..f21e920367 100755 --- a/t/t7422-submodule-output.sh +++ b/t/t7422-submodule-output.sh @@ -2,7 +2,6 @@ test_description='submodule --cached, --quiet etc. output' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-t3100.sh @@ -167,4 +166,11 @@ do ' done +test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' ' + { git submodule status --recursive 2>err; echo $?>status; } | + grep -q X/S && + test_must_be_empty err && + test_match_signal 13 "$(cat status)" +' + test_done diff --git a/t/t7423-submodule-symlinks.sh b/t/t7423-submodule-symlinks.sh index f45d806201..3d3c7af3ce 100755 --- a/t/t7423-submodule-symlinks.sh +++ b/t/t7423-submodule-symlinks.sh @@ -2,7 +2,6 @@ test_description='check that submodule operations do not follow symlinks' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'prepare' ' diff --git a/t/t7424-submodule-mixed-ref-formats.sh b/t/t7424-submodule-mixed-ref-formats.sh new file mode 100755 index 0000000000..559713b607 --- /dev/null +++ b/t/t7424-submodule-mixed-ref-formats.sh @@ -0,0 +1,143 @@ +#!/bin/sh + +test_description='submodules handle mixed ref storage formats' + +. ./test-lib.sh + +test_ref_format () { + echo "$2" >expect && + git -C "$1" rev-parse --show-ref-format >actual && + test_cmp expect actual +} + +for OTHER_FORMAT in files reftable +do + if test "$OTHER_FORMAT" = "$GIT_DEFAULT_REF_FORMAT" + then + continue + fi + +test_expect_success 'setup' ' + git config set --global protocol.file.allow always && + # Some tests migrate the ref storage format, which does not work with + # reflogs at the time of writing these tests. + git config set --global core.logAllRefUpdates false +' + +test_expect_success 'add existing repository with different ref storage format' ' + test_when_finished "rm -rf parent" && + + git init parent && + ( + cd parent && + test_commit parent && + git init --ref-format=$OTHER_FORMAT submodule && + test_commit -C submodule submodule && + git submodule add ./submodule + ) +' + +test_expect_success 'add submodules with different ref storage format' ' + test_when_finished "rm -rf submodule upstream" && + + git init submodule && + test_commit -C submodule submodule-initial && + git init upstream && + test_ref_format upstream "$GIT_DEFAULT_REF_FORMAT" && + git -C upstream submodule add --ref-format="$OTHER_FORMAT" "file://$(pwd)/submodule" && + test_ref_format upstream/submodule "$OTHER_FORMAT" +' + +test_expect_success 'recursive clone propagates ref storage format' ' + test_when_finished "rm -rf submodule upstream downstream" && + + git init submodule && + test_commit -C submodule submodule-initial && + git init upstream && + git -C upstream submodule add "file://$(pwd)/submodule" && + git -C upstream commit -am "add submodule" && + + # The upstream repository and its submodule should be using the default + # ref format. + test_ref_format upstream "$GIT_DEFAULT_REF_FORMAT" && + test_ref_format upstream/submodule "$GIT_DEFAULT_REF_FORMAT" && + + # The cloned repositories should use the other ref format that we have + # specified via `--ref-format`. The option should propagate to cloned + # submodules. + git clone --ref-format=$OTHER_FORMAT --recurse-submodules \ + upstream downstream && + test_ref_format downstream "$OTHER_FORMAT" && + test_ref_format downstream/submodule "$OTHER_FORMAT" +' + +test_expect_success 'clone submodules with different ref storage format' ' + test_when_finished "rm -rf submodule upstream downstream" && + + git init submodule && + test_commit -C submodule submodule-initial && + git init upstream && + git -C upstream submodule add "file://$(pwd)/submodule" && + git -C upstream commit -m "upstream submodule" && + + git clone --no-recurse-submodules "file://$(pwd)/upstream" downstream && + test_ref_format downstream "$GIT_DEFAULT_REF_FORMAT" && + git -C downstream submodule update --init --ref-format=$OTHER_FORMAT && + test_ref_format downstream/submodule "$OTHER_FORMAT" +' + +test_expect_success 'status with mixed submodule ref storages' ' + test_when_finished "rm -rf submodule main" && + + git init submodule && + test_commit -C submodule submodule-initial && + git init main && + git -C main submodule add "file://$(pwd)/submodule" && + git -C main commit -m "add submodule" && + git -C main/submodule refs migrate --ref-format=$OTHER_FORMAT && + + # The main repository should use the default ref format now, whereas + # the submodule should use the other format. + test_ref_format main "$GIT_DEFAULT_REF_FORMAT" && + test_ref_format main/submodule "$OTHER_FORMAT" && + + cat >expect <<-EOF && + $(git -C main/submodule rev-parse HEAD) submodule (submodule-initial) + EOF + git -C main submodule status >actual && + test_cmp expect actual +' + +test_expect_success 'recursive pull with mixed formats' ' + test_when_finished "rm -rf submodule upstream downstream" && + + # Set up the initial structure with an upstream repository that has a + # submodule, as well as a downstream clone of the upstream repository. + git init submodule && + test_commit -C submodule submodule-initial && + git init upstream && + git -C upstream submodule add "file://$(pwd)/submodule" && + git -C upstream commit -m "upstream submodule" && + + # Clone the upstream repository such that the main repo and its + # submodules have different formats. + git clone --no-recurse-submodules "file://$(pwd)/upstream" downstream && + git -C downstream submodule update --init --ref-format=$OTHER_FORMAT && + test_ref_format downstream "$GIT_DEFAULT_REF_FORMAT" && + test_ref_format downstream/submodule "$OTHER_FORMAT" && + + # Update the upstream submodule as well as the owning repository such + # that we can do a recursive pull. + test_commit -C submodule submodule-update && + git -C upstream/submodule pull && + git -C upstream commit -am "update the submodule" && + + git -C downstream pull --recurse-submodules && + git -C upstream/submodule rev-parse HEAD >expect && + git -C downstream/submodule rev-parse HEAD >actual && + test_cmp expect actual +' + +done + +test_done diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh index 4a9c22c9e2..9367794641 100755 --- a/t/t7450-bad-git-dotfiles.sh +++ b/t/t7450-bad-git-dotfiles.sh @@ -13,7 +13,6 @@ Such as: - symlinked .gitmodules, etc ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh index 52f5e28154..cc12f99f11 100755 --- a/t/t7501-commit-basic-functionality.sh +++ b/t/t7501-commit-basic-functionality.sh @@ -9,7 +9,6 @@ test_description='git commit' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-diff.sh" diff --git a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh index aa004b70a8..ad1eb64ba0 100755 --- a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh +++ b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh @@ -5,7 +5,6 @@ test_description='pre-commit and pre-merge-commit hooks' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'root commit' ' diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh index d1255228d5..c0f024eb1e 100755 --- a/t/t7504-commit-msg-hook.sh +++ b/t/t7504-commit-msg-hook.sh @@ -5,7 +5,6 @@ test_description='commit-msg hook' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'with no hook' ' diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index b88383df9e..2128142a61 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -5,7 +5,6 @@ test_description='prepare-commit-msg hook' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up commits for rebasing' ' diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index 46566d529e..185fe7e78e 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -2,7 +2,6 @@ test_description='git status for submodule' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_create_repo_with_commit () { diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh index 4c7db19ce7..b53d71c086 100755 --- a/t/t7507-commit-verbose.sh +++ b/t/t7507-commit-verbose.sh @@ -2,7 +2,6 @@ test_description='verbose commit template' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh write_script "check-for-diff" <<\EOF && diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 773383fefb..b2070d4e39 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -5,7 +5,6 @@ test_description='git status' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -1700,7 +1699,7 @@ test_expect_success 'setup slow status advice' ' EOF git add .gitignore && git commit -m "Add .gitignore" && - git config advice.statusuoption true + git config set advice.statusuoption true ) ' diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh index fd8c8f8f0b..8e373b566b 100755 --- a/t/t7509-commit-authorship.sh +++ b/t/t7509-commit-authorship.sh @@ -5,7 +5,6 @@ test_description='commit tests of various authorhip options. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh author_header () { diff --git a/t/t7511-status-index.sh b/t/t7511-status-index.sh index 4ffa45a7bf..b5fdc048a5 100755 --- a/t/t7511-status-index.sh +++ b/t/t7511-status-index.sh @@ -2,7 +2,6 @@ test_description='git status with certain file name lengths' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh files="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z" diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index cdd5f2c697..802f8f704c 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -10,7 +10,6 @@ test_description='git status advice' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index 3d3e13ccf8..818a8dafbd 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -175,6 +175,46 @@ test_expect_success 'with only a title in the message' ' test_cmp expected actual ' +test_expect_success 'with a bodiless message that lacks a trailing newline after the subject' ' + cat >expected <<-\EOF && + area: change + + Reviewed-by: Peff + Acked-by: Johan + EOF + printf "area: change" | + git interpret-trailers --trailer "Reviewed-by: Peff" \ + --trailer "Acked-by: Johan" >actual && + test_cmp expected actual +' + +test_expect_success 'with a bodied message that lacks a trailing newline after the body' ' + cat >expected <<-\EOF && + area: change + + details about the change. + + Reviewed-by: Peff + Acked-by: Johan + EOF + printf "area: change\n\ndetails about the change." | + git interpret-trailers --trailer "Reviewed-by: Peff" \ + --trailer "Acked-by: Johan" >actual && + test_cmp expected actual +' + +test_expect_success 'with a message that lacks a trailing newline after the trailers' ' + cat >expected <<-\EOF && + area: change + + Reviewed-by: Peff + Acked-by: Johan + EOF + printf "area: change\n\nReviewed-by: Peff" | + git interpret-trailers --trailer "Acked-by: Johan" >actual && + test_cmp expected actual +' + test_expect_success 'with multiline title in the message' ' cat >expected <<-\EOF && place of @@ -817,7 +857,7 @@ test_expect_success 'using "--where after" with "--no-where"' ' # the hardcoded default (in WHERE_END) assuming the absence of .gitconfig). # Here, the "start" setting of trailer.where is respected, so the new "Acked-by" # and "Bug" trailers are placed at the beginning, and not at the end which is -# the harcoded default. +# the hardcoded default. test_expect_success 'using "--where after" with "--no-where" defaults to configuration' ' test_config trailer.ack.key "Acked-by= " && test_config trailer.bug.key "Bug #" && @@ -841,7 +881,7 @@ test_expect_success 'using "--where after" with "--no-where" defaults to configu # immediately after it. For the next trailer (Bug #42), we default to using the # hardcoded WHERE_END because we don't have any "trailer.where" or # "trailer.bug.where" configured. -test_expect_success 'using "--no-where" defaults to harcoded default if nothing configured' ' +test_expect_success 'using "--no-where" defaults to hardcoded default if nothing configured' ' test_config trailer.ack.key "Acked-by= " && test_config trailer.bug.key "Bug #" && test_config trailer.separators ":=#" && diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh index 03ba0c0e73..075db69b42 100755 --- a/t/t7514-commit-patch.sh +++ b/t/t7514-commit-patch.sh @@ -2,7 +2,6 @@ test_description='hunk edit with "commit -p -m"' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup (initial)' ' diff --git a/t/t7515-status-symlinks.sh b/t/t7515-status-symlinks.sh index e3d6bb67bf..9f989be01b 100755 --- a/t/t7515-status-symlinks.sh +++ b/t/t7515-status-symlinks.sh @@ -2,7 +2,6 @@ test_description='git status and symlinks' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7516-commit-races.sh b/t/t7516-commit-races.sh index bb95f09810..de7c4ca790 100755 --- a/t/t7516-commit-races.sh +++ b/t/t7516-commit-races.sh @@ -2,7 +2,6 @@ test_description='git commit races' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'race to create orphan commit' ' diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh index efc6496e2b..163ae80468 100755 --- a/t/t7517-per-repo-email.sh +++ b/t/t7517-per-repo-email.sh @@ -9,7 +9,6 @@ test_description='per-repo forced setting of email address' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup a likely user.useConfigOnly use case' ' diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh index b37de0af49..d3ea4d603f 100755 --- a/t/t7518-ident-corner-cases.sh +++ b/t/t7518-ident-corner-cases.sh @@ -2,7 +2,6 @@ test_description='corner cases in ident strings' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # confirm that we do not segfault _and_ that we do not say "(null)", as diff --git a/t/t7520-ignored-hook-warning.sh b/t/t7520-ignored-hook-warning.sh index 3b63c34a30..bcfe15d51d 100755 --- a/t/t7520-ignored-hook-warning.sh +++ b/t/t7520-ignored-hook-warning.sh @@ -2,7 +2,6 @@ test_description='ignored hook warning' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7524-commit-summary.sh b/t/t7524-commit-summary.sh index 47b2f1dc22..82b5e4aa41 100755 --- a/t/t7524-commit-summary.sh +++ b/t/t7524-commit-summary.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='git commit summary' + . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7525-status-rename.sh b/t/t7525-status-rename.sh index a9210d3a3a..d409de1a33 100755 --- a/t/t7525-status-rename.sh +++ b/t/t7525-status-rename.sh @@ -2,7 +2,6 @@ test_description='git status rename detection options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7526-commit-pathspec-file.sh b/t/t7526-commit-pathspec-file.sh index c97c550021..3aabbf35a1 100755 --- a/t/t7526-commit-pathspec-file.sh +++ b/t/t7526-commit-pathspec-file.sh @@ -2,7 +2,6 @@ test_description='commit --pathspec-from-file' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 730f3c7f81..409cd0cd12 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -765,7 +765,7 @@ done # by the FSMonitor response to skip those recursive calls. That is, # even if FSMonitor says that the mtime of the submodule directory # hasn't changed and it could be implicitly marked valid, we must -# not take that shortcut. We need to force the recusion into the +# not take that shortcut. We need to force the recursion into the # submodule so that we get a summary of the status *within* the # submodule. @@ -907,6 +907,57 @@ test_expect_success "submodule absorbgitdirs implicitly starts daemon" ' test_subcommand git fsmonitor--daemon start <super-sub.trace ' +start_git_in_background () { + git "$@" & + git_pid=$! + git_pgid=$(ps -o pgid= -p $git_pid) + nr_tries_left=10 + while true + do + if test $nr_tries_left -eq 0 + then + kill -- -$git_pgid + exit 1 + fi + sleep 1 + nr_tries_left=$(($nr_tries_left - 1)) + done >/dev/null 2>&1 & + watchdog_pid=$! + wait $git_pid +} + +stop_git () { + while kill -0 -- -$git_pgid + do + kill -- -$git_pgid + sleep 1 + done +} + +stop_watchdog () { + while kill -0 $watchdog_pid + do + kill $watchdog_pid + sleep 1 + done +} + +test_expect_success !MINGW "submodule implicitly starts daemon by pull" ' + test_atexit "stop_watchdog" && + test_when_finished "stop_git; rm -rf cloned super sub" && + + create_super super && + create_sub sub && + + git -C super submodule add ../sub ./dir_1/dir_2/sub && + git -C super commit -m "add sub" && + git clone --recurse-submodules super cloned && + + git -C cloned/dir_1/dir_2/sub config core.fsmonitor true && + set -m && + start_git_in_background -C cloned pull --recurse-submodules +' + # On a case-insensitive file system, confirm that the daemon # notices when the .git directory is moved/renamed/deleted # regardless of how it is spelled in the FS event. diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 65fd3d8552..ef54cff4fa 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -29,7 +29,6 @@ Testing basic merge operations/option parsing. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh index a94387a75f..199a1d5db3 100755 --- a/t/t7601-merge-pull-config.sh +++ b/t/t7601-merge-pull-config.sh @@ -280,7 +280,7 @@ test_expect_success '--rebase overrides pull.ff unset' ' test_does_rebase pull --rebase ' -# Group 4: --no-rebase heeds pull.ff=!only or explict --ff or --no-ff +# Group 4: --no-rebase heeds pull.ff=!only or explicit --ff or --no-ff test_expect_success '--no-rebase works with --no-ff' ' test_does_merge_when_ff_possible pull --no-rebase --no-ff diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index 3669d33bd5..ff085b086c 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -4,7 +4,6 @@ test_description='git merge Testing octopus merge with more than 25 refs.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh index 0e85b21ec8..4887ca705b 100755 --- a/t/t7603-merge-reduce-heads.sh +++ b/t/t7603-merge-reduce-heads.sh @@ -4,7 +4,6 @@ test_description='git merge Testing octopus merge when reducing parents to independent branches.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # 0 - 1 diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh index eca7555101..cd4f9607dc 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -4,7 +4,6 @@ test_description='git merge Testing merge when using a custom message for the merge commit.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh create_merge_msgs() { diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh index 62d935d31c..5d56c38546 100755 --- a/t/t7605-merge-resolve.sh +++ b/t/t7605-merge-resolve.sh @@ -4,7 +4,6 @@ test_description='git merge Testing the resolve strategy.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7606-merge-custom.sh b/t/t7606-merge-custom.sh index 135cb23085..81fb7c474c 100755 --- a/t/t7606-merge-custom.sh +++ b/t/t7606-merge-custom.sh @@ -14,7 +14,6 @@ Testing a custom strategy. * (tag: c0) c0 " -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'set up custom strategy' ' diff --git a/t/t7607-merge-state.sh b/t/t7607-merge-state.sh index 9001674f2e..89a62ac53b 100755 --- a/t/t7607-merge-state.sh +++ b/t/t7607-merge-state.sh @@ -4,7 +4,6 @@ test_description="Test that merge state is as expected after failed merge" GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'Ensure we restore original state if no merge strategy handles it' ' diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh index 2179938c43..0b908ab2e7 100755 --- a/t/t7608-merge-messages.sh +++ b/t/t7608-merge-messages.sh @@ -4,7 +4,6 @@ test_description='test auto-generated merge messages' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_oneline() { diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh index 8b1c3bd39f..330d6d603d 100755 --- a/t/t7609-mergetool--lib.sh +++ b/t/t7609-mergetool--lib.sh @@ -4,7 +4,6 @@ test_description='git mergetool Testing basic merge tools options' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'mergetool --tool=vimdiff creates the expected layout' ' diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 22b3a85b3e..c077aba7ce 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -898,4 +898,12 @@ test_expect_success 'mergetool with guiDefault' ' git commit -m "branch1 resolved with mergetool" ' +test_expect_success 'mergetool with non-existent tool' ' + test_when_finished "git reset --hard" && + git checkout -b test$test_count branch1 && + test_must_fail git merge main && + yes "" | test_must_fail git mergetool --tool=absent >out 2>&1 && + test_grep "mergetool.absent.cmd not set for tool" out +' + test_done diff --git a/t/t7611-merge-abort.sh b/t/t7611-merge-abort.sh index 992a8f9874..d6975ca48d 100755 --- a/t/t7611-merge-abort.sh +++ b/t/t7611-merge-abort.sh @@ -25,7 +25,6 @@ Next, test git merge --abort with the following variables: GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh index 84ddb56851..337fac0d84 100755 --- a/t/t7612-merge-verify-signatures.sh +++ b/t/t7612-merge-verify-signatures.sh @@ -4,7 +4,6 @@ test_description='merge signature verification tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" diff --git a/t/t7614-merge-signoff.sh b/t/t7614-merge-signoff.sh index cf96a35e8e..fee258d4f0 100755 --- a/t/t7614-merge-signoff.sh +++ b/t/t7614-merge-signoff.sh @@ -8,7 +8,6 @@ This test runs git merge --signoff and makes sure that it works. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Setup test files diff --git a/t/t7615-diff-algo-with-mergy-operations.sh b/t/t7615-diff-algo-with-mergy-operations.sh new file mode 100755 index 0000000000..3b1aad0167 --- /dev/null +++ b/t/t7615-diff-algo-with-mergy-operations.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +test_description='git merge and other operations that rely on merge + +Testing the influence of the diff algorithm on the merge output.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + cp "$TEST_DIRECTORY"/t7615/base.c file.c && + git add file.c && + git commit -m c0 && + git tag c0 && + cp "$TEST_DIRECTORY"/t7615/ours.c file.c && + git add file.c && + git commit -m c1 && + git tag c1 && + git reset --hard c0 && + cp "$TEST_DIRECTORY"/t7615/theirs.c file.c && + git add file.c && + git commit -m c2 && + git tag c2 +' + +GIT_TEST_MERGE_ALGORITHM=recursive + +test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' + git reset --hard c1 && + test_must_fail git merge -s recursive c2 +' + +test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' ' + git reset --hard c1 && + git merge --strategy recursive -Xdiff-algorithm=histogram c2 +' + +test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' ' + git reset --hard c1 && + git config diff.algorithm histogram && + git merge --strategy recursive c2 +' + +test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' + git reset --hard c1 && + test_must_fail git cherry-pick -s recursive c2 +' + +test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' ' + git reset --hard c1 && + git cherry-pick --strategy recursive -Xdiff-algorithm=histogram c2 +' + +test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' ' + git reset --hard c1 && + git config diff.algorithm histogram && + git cherry-pick --strategy recursive c2 +' + +test_done diff --git a/t/t7615/base.c b/t/t7615/base.c new file mode 100644 index 0000000000..c64abc5936 --- /dev/null +++ b/t/t7615/base.c @@ -0,0 +1,17 @@ +int f(int x, int y) +{ + if (x == 0) + { + return y; + } + return x; +} + +int g(size_t u) +{ + while (u < 30) + { + u++; + } + return u; +} diff --git a/t/t7615/ours.c b/t/t7615/ours.c new file mode 100644 index 0000000000..44d8251397 --- /dev/null +++ b/t/t7615/ours.c @@ -0,0 +1,17 @@ +int g(size_t u) +{ + while (u < 30) + { + u++; + } + return u; +} + +int h(int x, int y, int z) +{ + if (z == 0) + { + return x; + } + return y; +} diff --git a/t/t7615/theirs.c b/t/t7615/theirs.c new file mode 100644 index 0000000000..85f02146fe --- /dev/null +++ b/t/t7615/theirs.c @@ -0,0 +1,17 @@ +int f(int x, int y) +{ + if (x == 0) + { + return y; + } + return x; +} + +int g(size_t u) +{ + while (u > 34) + { + u--; + } + return u; +} diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 127efe99f8..be1188e736 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -7,6 +7,9 @@ test_description='git repack works correctly' . "${TEST_DIRECTORY}/lib-midx.sh" . "${TEST_DIRECTORY}/lib-terminal.sh" +GIT_TEST_MULTI_PACK_INDEX=0 +GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 + commit_and_pack () { test_commit "$@" 1>&2 && incrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) && @@ -70,14 +73,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' ' test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' ' # build on $oid, $packid, and .keep state from previous - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 git repack -Adbl && + git repack -Adbl && test_has_duplicate_object true ' test_expect_success 'writing bitmaps via config can duplicate .keep objects' ' # build on $oid, $packid, and .keep state from previous - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -c repack.writebitmaps=true repack -Adl && + git -c repack.writebitmaps=true repack -Adl && test_has_duplicate_object true ' @@ -118,7 +120,7 @@ test_expect_success '--local disables writing bitmaps when connected to alternat ( cd member && test_commit "object" && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err && + git repack -Adl --write-bitmap-index 2>err && cat >expect <<-EOF && warning: disabling bitmap writing, as some objects are not being packed EOF @@ -284,8 +286,7 @@ test_expect_success 'repacking fails when missing .pack actually means missing o test_expect_success 'bitmaps are created by default in bare repos' ' git clone --bare .git bare.git && rm -f bare.git/objects/pack/*.bitmap && - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -C bare.git repack -ad && + git -C bare.git repack -ad && bitmap=$(ls bare.git/objects/pack/*.bitmap) && test_path_is_file "$bitmap" ' @@ -296,8 +297,7 @@ test_expect_success 'incremental repack does not complain' ' ' test_expect_success 'bitmaps can be disabled on bare repos' ' - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -c repack.writeBitmaps=false -C bare.git repack -ad && + git -c repack.writeBitmaps=false -C bare.git repack -ad && bitmap=$(ls bare.git/objects/pack/*.bitmap || :) && test -z "$bitmap" ' @@ -308,8 +308,7 @@ test_expect_success 'no bitmaps created if .keep files present' ' keep=${pack%.pack}.keep && test_when_finished "rm -f \"\$keep\"" && >"$keep" && - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -C bare.git repack -ad 2>stderr && + git -C bare.git repack -ad 2>stderr && test_must_be_empty stderr && find bare.git/objects/pack/ -type f -name "*.bitmap" >actual && test_must_be_empty actual @@ -320,8 +319,7 @@ test_expect_success 'auto-bitmaps do not complain if unavailable' ' blob=$(test-tool genrandom big $((1024*1024)) | git -C bare.git hash-object -w --stdin) && git -C bare.git update-ref refs/tags/big $blob && - GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -C bare.git repack -ad 2>stderr && + git -C bare.git repack -ad 2>stderr && test_must_be_empty stderr && find bare.git/objects/pack -type f -name "*.bitmap" >actual && test_must_be_empty actual @@ -342,9 +340,7 @@ test_expect_success 'repacking with a filter works' ' ' test_expect_success '--filter fails with --write-bitmap-index' ' - test_must_fail \ - env GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ - git -C bare.git repack -a -d --write-bitmap-index --filter=blob:none + test_must_fail git -C bare.git repack -a -d --write-bitmap-index --filter=blob:none ' test_expect_success 'repacking with two filters works' ' @@ -540,11 +536,11 @@ test_expect_success 'setup for --write-midx tests' ' test_expect_success '--write-midx unchanged' ' ( cd midx && - GIT_TEST_MULTI_PACK_INDEX=0 git repack && + git repack && test_path_is_missing $midx && test_path_is_missing $midx-*.bitmap && - GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx && + git repack --write-midx && test_path_is_file $midx && test_path_is_missing $midx-*.bitmap && @@ -557,7 +553,7 @@ test_expect_success '--write-midx with a new pack' ' cd midx && test_commit loose && - GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx && + git repack --write-midx && test_path_is_file $midx && test_path_is_missing $midx-*.bitmap && @@ -568,7 +564,7 @@ test_expect_success '--write-midx with a new pack' ' test_expect_success '--write-midx with -b' ' ( cd midx && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -mb && + git repack -mb && test_path_is_file $midx && test_path_is_file $midx-*.bitmap && @@ -581,7 +577,7 @@ test_expect_success '--write-midx with -d' ' cd midx && test_commit repack && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ad --write-midx && + git repack -Ad --write-midx && test_path_is_file $midx && test_path_is_missing $midx-*.bitmap && @@ -594,21 +590,21 @@ test_expect_success 'cleans up MIDX when appropriate' ' cd midx && test_commit repack-2 && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx && + git repack -Adb --write-midx && checksum=$(midx_checksum $objdir) && test_path_is_file $midx && test_path_is_file $midx-$checksum.bitmap && test_commit repack-3 && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx && + git repack -Adb --write-midx && test_path_is_file $midx && test_path_is_missing $midx-$checksum.bitmap && test_path_is_file $midx-$(midx_checksum $objdir).bitmap && test_commit repack-4 && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb && + git repack -Adb && find $objdir/pack -type f -name "multi-pack-index*" >files && test_must_be_empty files @@ -629,7 +625,6 @@ test_expect_success '--write-midx with preferred bitmap tips' ' git log --format="create refs/tags/%s/%s %H" HEAD >refs && git update-ref --stdin <refs && - GIT_TEST_MULTI_PACK_INDEX=0 \ git repack --write-midx --write-bitmap-index && test_path_is_file $midx && test_path_is_file $midx-$(midx_checksum $objdir).bitmap && @@ -721,13 +716,13 @@ test_expect_success '--write-midx removes stale pack-based bitmaps' ' ( cd repo && test_commit base && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ab && + git repack -Ab && pack_bitmap=$(ls $objdir/pack/pack-*.bitmap) && test_path_is_file "$pack_bitmap" && test_commit tip && - GIT_TEST_MULTI_PACK_INDEX=0 git repack -bm && + git repack -bm && test_path_is_file $midx && test_path_is_file $midx-$(midx_checksum $objdir).bitmap && @@ -750,7 +745,6 @@ test_expect_success '--write-midx with --pack-kept-objects' ' keep="$objdir/pack/pack-$one.keep" && touch "$keep" && - GIT_TEST_MULTI_PACK_INDEX=0 \ git repack --write-midx --write-bitmap-index --geometric=2 -d \ --pack-kept-objects && diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index fe6c3e77a3..5715f4d69a 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -5,7 +5,6 @@ test_description='git repack works correctly' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh fsha1= diff --git a/t/t7702-repack-cyclic-alternate.sh b/t/t7702-repack-cyclic-alternate.sh index f3cdb98eec..cd91766e78 100755 --- a/t/t7702-repack-cyclic-alternate.sh +++ b/t/t7702-repack-cyclic-alternate.sh @@ -5,7 +5,6 @@ test_description='repack involving cyclic alternate' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' @@ -18,7 +17,7 @@ test_expect_success setup ' echo "$(pwd)"/.git/objects/../objects >.git/objects/info/alternates ' -test_expect_success 're-packing repository with itsself as alternate' ' +test_expect_success 're-packing repository with itself as alternate' ' git repack -adl && git fsck ' diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index 71e1ef3a10..959e6e2648 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -330,7 +330,7 @@ test_expect_success '--max-cruft-size with pruning' ' # repack (and prune) with a --max-cruft-size to ensure # that we appropriately split the resulting set of packs git repack -d --cruft --max-cruft-size=1M \ - --cruft-expiration=10.seconds.ago && + --cruft-expiration=1000.seconds.ago && ls $packdir/pack-*.mtimes | sort >cruft.after && for cruft in $(cat cruft.after) diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index cc917b257e..9b74db5563 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -665,6 +665,10 @@ run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' ' test_cmp expect file ' +run_dir_diff_test 'difftool --dir-diff with no diff' ' + git difftool -d main main +' + write_script modify-file <<\EOF echo "new content" >file EOF diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 875dcfd98f..64ac4f04ee 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -31,6 +31,7 @@ int main(int argc, const char **argv) return 0; /* char ?? */ } + EOF test_expect_success setup ' @@ -86,6 +87,7 @@ test_expect_success setup ' # Still a no-op. function dummy() {} EOF + printf "\200\nASCII\n" >invalid-utf8 && if test_have_prereq FUNNYNAMES then echo unusual >"\"unusual\" pathname" && @@ -533,6 +535,14 @@ do test_cmp expected actual ' + test_expect_success "grep $L searches past invalid lines on UTF-8 locale" ' + LC_ALL=en_US.UTF-8 git grep A. invalid-utf8 >actual && + cat >expected <<-EOF && + invalid-utf8:ASCII + EOF + test_cmp expected actual + ' + test_expect_success FUNNYNAMES "grep $L should quote unusual pathnames" ' cat >expected <<-EOF && ${HC}"\"unusual\" pathname":unusual diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh index fe38d88a1a..3160be59fd 100755 --- a/t/t7811-grep-open.sh +++ b/t/t7811-grep-open.sh @@ -3,7 +3,6 @@ test_description='git grep --open-files-in-pager ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pager.sh unset PAGER GIT_PAGER diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh index 31c66b63c2..ac7be54714 100755 --- a/t/t7812-grep-icase-non-ascii.sh +++ b/t/t7812-grep-icase-non-ascii.sh @@ -2,7 +2,6 @@ test_description='grep icase on non-English locales' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh doalarm () { diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh index 1227885737..701e08a8e5 100755 --- a/t/t7813-grep-icase-iso.sh +++ b/t/t7813-grep-icase-iso.sh @@ -2,7 +2,6 @@ test_description='grep icase on non-English locales' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh test_expect_success GETTEXT_ISO_LOCALE 'setup' ' diff --git a/t/t7815-grep-binary.sh b/t/t7815-grep-binary.sh index ac871287c0..90ebb64f46 100755 --- a/t/t7815-grep-binary.sh +++ b/t/t7815-grep-binary.sh @@ -2,7 +2,6 @@ test_description='git grep in binary files' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' " diff --git a/t/t7816-grep-binary-pattern.sh b/t/t7816-grep-binary-pattern.sh index 4353be5adb..0088eaa0c9 100755 --- a/t/t7816-grep-binary-pattern.sh +++ b/t/t7816-grep-binary-pattern.sh @@ -2,7 +2,6 @@ test_description='git grep with a binary pattern files' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh nul_match_internal () { diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 8595489ceb..0ce4ba1cbe 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -49,22 +49,47 @@ test_expect_success 'run [--auto|--quiet]' ' git maintenance run --auto 2>/dev/null && GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \ git maintenance run --no-quiet 2>/dev/null && - test_subcommand git gc --quiet <run-no-auto.txt && - test_subcommand ! git gc --auto --quiet <run-auto.txt && - test_subcommand git gc --no-quiet <run-no-quiet.txt + test_subcommand git gc --quiet --no-detach <run-no-auto.txt && + test_subcommand ! git gc --auto --quiet --no-detach <run-auto.txt && + test_subcommand git gc --no-quiet --no-detach <run-no-quiet.txt ' test_expect_success 'maintenance.auto config option' ' GIT_TRACE2_EVENT="$(pwd)/default" git commit --quiet --allow-empty -m 1 && - test_subcommand git maintenance run --auto --quiet <default && + test_subcommand git maintenance run --auto --quiet --detach <default && GIT_TRACE2_EVENT="$(pwd)/true" \ git -c maintenance.auto=true \ commit --quiet --allow-empty -m 2 && - test_subcommand git maintenance run --auto --quiet <true && + test_subcommand git maintenance run --auto --quiet --detach <true && GIT_TRACE2_EVENT="$(pwd)/false" \ git -c maintenance.auto=false \ commit --quiet --allow-empty -m 3 && - test_subcommand ! git maintenance run --auto --quiet <false + test_subcommand ! git maintenance run --auto --quiet --detach <false +' + +for cfg in maintenance.autoDetach gc.autoDetach +do + test_expect_success "$cfg=true config option" ' + test_when_finished "rm -f trace" && + test_config $cfg true && + GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 && + test_subcommand git maintenance run --auto --quiet --detach <trace + ' + + test_expect_success "$cfg=false config option" ' + test_when_finished "rm -f trace" && + test_config $cfg false && + GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 && + test_subcommand git maintenance run --auto --quiet --no-detach <trace + ' +done + +test_expect_success "maintenance.autoDetach overrides gc.autoDetach" ' + test_when_finished "rm -f trace" && + test_config maintenance.autoDetach false && + test_config gc.autoDetach true && + GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 && + test_subcommand git maintenance run --auto --quiet --no-detach <trace ' test_expect_success 'register uses XDG_CONFIG_HOME config if it exists' ' @@ -129,9 +154,9 @@ test_expect_success 'run --task=<task>' ' git maintenance run --task=commit-graph 2>/dev/null && GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \ git maintenance run --task=commit-graph --task=gc 2>/dev/null && - test_subcommand ! git gc --quiet <run-commit-graph.txt && - test_subcommand git gc --quiet <run-gc.txt && - test_subcommand git gc --quiet <run-both.txt && + test_subcommand ! git gc --quiet --no-detach <run-commit-graph.txt && + test_subcommand git gc --quiet --no-detach <run-gc.txt && + test_subcommand git gc --quiet --no-detach <run-both.txt && test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt && test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt && test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt @@ -620,6 +645,22 @@ test_expect_success !MINGW 'register and unregister with regex metacharacters' ' maintenance.repo "$(pwd)/$META" ' +test_expect_success 'start without GIT_TEST_MAINT_SCHEDULER' ' + test_when_finished "rm -rf systemctl.log script repo" && + mkdir script && + write_script script/systemctl <<-\EOF && + echo "$*" >>../systemctl.log + EOF + git init repo && + ( + cd repo && + sane_unset GIT_TEST_MAINT_SCHEDULER && + PATH="$PWD/../script:$PATH" git maintenance start --scheduler=systemd + ) && + test_grep -- "--user list-timers" systemctl.log && + test_grep -- "enable --now git-maintenance@" systemctl.log +' + test_expect_success 'start --scheduler=<scheduler>' ' test_expect_code 129 git maintenance start --scheduler=foo 2>err && test_grep "unrecognized --scheduler argument" err && @@ -800,6 +841,9 @@ test_expect_success 'start and stop Linux/systemd maintenance' ' test_systemd_analyze_verify "systemd/user/git-maintenance@daily.service" && test_systemd_analyze_verify "systemd/user/git-maintenance@weekly.service" && + grep "core.askPass=true" "systemd/user/git-maintenance@.service" && + grep "credential.interactive=false" "systemd/user/git-maintenance@.service" && + printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect && test_cmp expect args && @@ -908,4 +952,75 @@ test_expect_success 'failed schedule prevents config change' ' done ' +test_expect_success '--no-detach causes maintenance to not run in background' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + # Prepare the repository such that git-maintenance(1) ends up + # outputting something. + test_commit something && + git config set maintenance.gc.enabled false && + git config set maintenance.loose-objects.enabled true && + git config set maintenance.loose-objects.auto 1 && + git config set maintenance.incremental-repack.enabled true && + + GIT_TRACE2_EVENT="$(pwd)/trace.txt" \ + git maintenance run --no-detach >out 2>&1 && + ! test_region maintenance detach trace.txt + ) +' + +test_expect_success '--detach causes maintenance to run in background' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit something && + git config set maintenance.gc.enabled false && + git config set maintenance.loose-objects.enabled true && + git config set maintenance.loose-objects.auto 1 && + git config set maintenance.incremental-repack.enabled true && + + # The extra file descriptor gets inherited to the child + # process, and by reading stdout we thus essentially wait for + # that descriptor to get closed, which indicates that the child + # is done, too. + does_not_matter=$(GIT_TRACE2_EVENT="$(pwd)/trace.txt" \ + git maintenance run --detach 9>&1) && + test_region maintenance detach trace.txt + ) +' + +test_expect_success 'repacking loose objects is quiet' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit something && + git config set maintenance.gc.enabled false && + git config set maintenance.loose-objects.enabled true && + git config set maintenance.loose-objects.auto 1 && + + git maintenance run --quiet >out 2>&1 && + test_must_be_empty out + ) +' + +test_expect_success 'maintenance aborts with existing lock file' ' + test_when_finished "rm -rf repo script" && + mkdir script && + write_script script/systemctl <<-\EOF && + true + EOF + + git init repo && + : >repo/.git/objects/schedule.lock && + test_must_fail env PATH="$PWD/script:$PATH" git -C repo maintenance start --scheduler=systemd 2>err && + test_grep "Another scheduled git-maintenance(1) process seems to be running" err +' + test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index 3596634039..0147de304b 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -5,7 +5,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh PROG='git blame -c' diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index 6288352f57..731265541a 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -4,7 +4,6 @@ test_description='git blame corner cases' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/' diff --git a/t/t8004-blame-with-conflicts.sh b/t/t8004-blame-with-conflicts.sh index 2c2a0b33f9..35414a5336 100755 --- a/t/t8004-blame-with-conflicts.sh +++ b/t/t8004-blame-with-conflicts.sh @@ -6,7 +6,6 @@ test_description='git blame on conflicted files' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup first case' ' diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh index 75da219ed1..81847ffb9a 100755 --- a/t/t8005-blame-i18n.sh +++ b/t/t8005-blame-i18n.sh @@ -1,8 +1,15 @@ #!/bin/sh test_description='git blame encoding conversion' + . ./test-lib.sh +if ! test_have_prereq ICONV +then + skip_all='skipping blame i18n tests; iconv not available' + test_done +fi + . "$TEST_DIRECTORY"/t8005/utf8.txt . "$TEST_DIRECTORY"/t8005/euc-japan.txt . "$TEST_DIRECTORY"/t8005/sjis.txt diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh index 42f8be25a3..07a287ffd3 100755 --- a/t/t8006-blame-textconv.sh +++ b/t/t8006-blame-textconv.sh @@ -2,7 +2,6 @@ test_description='git blame textconv support' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh find_blame() { diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh index c8266f17f1..c3735fb50d 100755 --- a/t/t8007-cat-file-textconv.sh +++ b/t/t8007-cat-file-textconv.sh @@ -2,7 +2,6 @@ test_description='git cat-file textconv support' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >helper <<'EOF' diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh index fb5d225a67..c12a4196d6 100755 --- a/t/t8008-blame-formats.sh +++ b/t/t8008-blame-formats.sh @@ -2,7 +2,6 @@ test_description='blame output in various formats on a simple case' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t8009-blame-vs-topicbranches.sh b/t/t8009-blame-vs-topicbranches.sh index 30331713b9..c808b81962 100755 --- a/t/t8009-blame-vs-topicbranches.sh +++ b/t/t8009-blame-vs-topicbranches.sh @@ -1,8 +1,7 @@ #!/bin/sh -test_description='blaming trough history with topic branches' +test_description='blaming through history with topic branches' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Creates the history shown below. '*'s mark the first parent in the merges. diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh index eb64b766bd..b3be2aa387 100755 --- a/t/t8010-cat-file-filters.sh +++ b/t/t8010-cat-file-filters.sh @@ -2,7 +2,6 @@ test_description='git cat-file filters support' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ' ' diff --git a/t/t8011-blame-split-file.sh b/t/t8011-blame-split-file.sh index da1801f4d2..c66494f5ba 100755 --- a/t/t8011-blame-split-file.sh +++ b/t/t8011-blame-split-file.sh @@ -11,7 +11,6 @@ not bother testing that the non-C case fails to find it. That is how blame behaves now, but it is not a property we want to make sure is retained. ' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # help avoid typing and reading long strings of similar lines diff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh index 9a79c109f2..c3a5f6d01f 100755 --- a/t/t8012-blame-colors.sh +++ b/t/t8012-blame-colors.sh @@ -5,7 +5,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh PROG='git blame -c' diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh index d33788d867..370b768149 100755 --- a/t/t8013-blame-ignore-revs.sh +++ b/t/t8013-blame-ignore-revs.sh @@ -2,7 +2,6 @@ test_description='ignore revisions when blaming' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Creates: diff --git a/t/t8014-blame-ignore-fuzzy.sh b/t/t8014-blame-ignore-fuzzy.sh index 933222cea1..f5dcbd9e82 100755 --- a/t/t8014-blame-ignore-fuzzy.sh +++ b/t/t8014-blame-ignore-fuzzy.sh @@ -2,7 +2,6 @@ test_description='git blame ignore fuzzy heuristic' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/' diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 64a4ab3736..0c1af43f6f 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -4,7 +4,6 @@ test_description='git send-email' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # May be altered later in the test @@ -1324,7 +1323,7 @@ test_expect_success $PREREQ 'cc list is sanitized' ' Reviewed-by: Füñný Nâmé <odd_?=mail@example.com> Reported-by: bugger on Jira Reported-by: Douglas Reporter <doug@example.com> [from Jira profile] - BugID: 12345 + BugID: 12345should-not-appear Co-developed-by: "C. O. Developer" <codev@example.com> Signed-off-by: A. U. Thor <thor.au@example.com> EOF @@ -1337,7 +1336,7 @@ test_expect_success $PREREQ 'cc list is sanitized' ' " <odd_?=mail@example.com>" actual-show-all-headers && test_grep "^(body) Ignoring Reported-by .* bugger on Jira" actual-show-all-headers && test_grep "^(body) Adding cc: Douglas Reporter <doug@example.com>" actual-show-all-headers && - test_grep ! "12345" actual-show-all-headers && + test_grep ! "12345should-not-appear" actual-show-all-headers && test_grep "^(body) Adding cc: \"C. O. Developer\" <codev@example.com>" actual-show-all-headers && test_grep "^(body) Adding cc: \"A. U. Thor\" <thor.au@example.com>" actual-show-all-headers ' @@ -2084,22 +2083,24 @@ test_dump_aliases '--dump-aliases mailrc format' \ 'bob' \ 'chloe' \ 'eve' <<-\EOF - alias alice Alice W Land <awol@example.com> - alias eve Eve <eve@example.com> - alias bob Robert Bobbyton <bob@example.com> + alias alice "Alice W Land <awol@example.com>" + alias eve "Eve <eve@example.com>" + alias bob "Robert Bobbyton <bob@example.com>" alias chloe chloe@example.com EOF test_dump_aliases '--dump-aliases pine format' \ 'pine' \ 'alice' \ + 'bcgrp' \ 'bob' \ 'chloe' \ 'eve' <<-\EOF - alice Alice W Land <awol@example.com> - eve Eve <eve@example.com> - bob Robert Bobbyton <bob@example.com> + alice Alice W Land awol@example.com Friend + eve Eve eve@example.com + bob Robert Bobbyton bob@example.com chloe chloe@example.com + bcgrp (bob, chloe, Other <o@example.com>) EOF test_dump_aliases '--dump-aliases gnus format' \ @@ -2118,6 +2119,110 @@ test_expect_success '--dump-aliases must be used alone' ' test_must_fail git send-email --dump-aliases --to=janice@example.com -1 refs/heads/accounting ' +test_translate_aliases () { + msg="$1" && shift && + filetype="$1" && shift && + aliases="$1" && shift && + printf '%s\n' "$@" >expect && + cat >.tmp-email-aliases && + printf '%s\n' "$aliases" >aliases && + + test_expect_success $PREREQ "$msg" ' + clean_fake_sendmail && rm -fr outdir && + git config --replace-all sendemail.aliasesfile \ + "$(pwd)/.tmp-email-aliases" && + git config sendemail.aliasfiletype "$filetype" && + git send-email --translate-aliases <aliases 2>errors >actual && + test_cmp expect actual + ' +} + +test_translate_aliases '--translate-aliases sendmail format' \ + 'sendmail' \ + 'alice bcgrp' \ + 'Alice W Land <awol@example.com>' \ + 'Robert Bobbyton <bob@example.com>' \ + 'chloe@example.com' \ + 'Other <o@example.com>' <<-\EOF + alice: Alice W Land <awol@example.com> + bob: Robert Bobbyton <bob@example.com> + chloe: chloe@example.com + abgroup: alice, bob + bcgrp: bob, chloe, Other <o@example.com> + EOF + +test_translate_aliases '--translate-aliases mutt format' \ + 'mutt' \ + 'donald bob' \ + 'Donald C Carlton <donc@example.com>' \ + 'Robert Bobbyton <bob@example.com>' <<-\EOF + alias alice Alice W Land <awol@example.com> + alias donald Donald C Carlton <donc@example.com> + alias bob Robert Bobbyton <bob@example.com> + alias chloe chloe@example.com + EOF + +test_translate_aliases '--translate-aliases mailrc format' \ + 'mailrc' \ + 'chloe eve alice' \ + 'chloe@example.com' \ + 'Eve <eve@example.com>' \ + 'Alice W Land <awol@example.com>' <<-\EOF + alias alice "Alice W Land <awol@example.com>" + alias eve "Eve <eve@example.com>" + alias bob "Robert Bobbyton <bob@example.com>" + alias chloe chloe@example.com + EOF + +test_translate_aliases '--translate-aliases pine format' \ + 'pine' \ + 'eve bob bcgrp' \ + 'eve@example.com' \ + 'bob@example.com' \ + 'bob@example.com' \ + 'chloe@example.com' \ + 'Other <o@example.com>' <<-\EOF + alice Alice W Land awol@example.com Friend + eve Eve eve@example.com + bob Robert Bobbyton bob@example.com + chloe chloe@example.com + bcgrp (bob, chloe, Other <o@example.com>) + EOF + +test_translate_aliases '--translate-aliases gnus format' \ + 'gnus' \ + 'alice chloe eve' \ + 'awol@example.com' \ + 'chloe@example.com' \ + 'eve@example.com' <<-\EOF + (define-mail-alias "alice" "awol@example.com") + (define-mail-alias "eve" "eve@example.com") + (define-mail-alias "bob" "bob@example.com") + (define-mail-alias "chloe" "chloe@example.com") + EOF + +test_expect_success $PREREQ '--translate-aliases passes valid addresses through' ' + cat >expect <<-\EOF && + Other <o@example.com> + EOF + cat >aliases <<-\EOF && + Other <o@example.com> + EOF + git send-email --translate-aliases <aliases >actual && + test_cmp expect actual +' + +test_expect_success $PREREQ '--translate-aliases passes unknown aliases through' ' + cat >expect <<-\EOF && + blargh + EOF + cat >aliases <<-\EOF && + blargh + EOF + git send-email --translate-aliases <aliases >actual && + test_cmp expect actual +' + test_expect_success $PREREQ 'aliases and sendemail.identity' ' test_must_fail git \ -c sendemail.identity=cloud \ @@ -2379,6 +2484,128 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' ' test_cmp expected-list actual-list ' +test_expect_success $PREREQ 'mailmap support with --to' ' + clean_fake_sendmail && + test_config mailmap.file "mailmap.test" && + cat >mailmap.test <<-EOF && + Some Body <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --to=someone@example.org \ + --mailmap \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + +test_expect_success $PREREQ 'sendemail.mailmap configuration' ' + clean_fake_sendmail && + test_config mailmap.file "mailmap.test" && + test_config sendemail.mailmap "true" && + cat >mailmap.test <<-EOF && + Some Body <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --to=someone@example.org \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + +test_expect_success $PREREQ 'sendemail.mailmap.file configuration' ' + clean_fake_sendmail && + test_config sendemail.mailmap.file "mailmap.test" && + test_config sendemail.mailmap "true" && + cat >mailmap.test <<-EOF && + Some Body <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --to=someone@example.org \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + +test_expect_success $PREREQ 'sendemail.mailmap identity overrides configuration' ' + clean_fake_sendmail && + test_config sendemail.cloud.mailmap.file "mailmap.test" && + test_config sendemail.mailmap "false" && + test_config sendemail.cloud.mailmap "true" && + cat >mailmap.test <<-EOF && + Some Body <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --identity=cloud \ + --to=someone@example.org \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + +test_expect_success $PREREQ '--no-mailmap overrides configuration' ' + clean_fake_sendmail && + test_config sendemail.cloud.mailmap.file "mailmap.test" && + test_config sendemail.mailmap "false" && + test_config sendemail.cloud.mailmap "true" && + cat >mailmap.test <<-EOF && + Some Body <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --identity=cloud \ + --to=someone@example.org \ + --no-mailmap \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.org!$" commandline1 +' + +test_expect_success $PREREQ 'mailmap support in To header' ' + clean_fake_sendmail && + test_config mailmap.file "mailmap.test" && + cat >mailmap.test <<-EOF && + <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 --to=someone@example.org >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --mailmap \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + +test_expect_success $PREREQ 'mailmap support in Cc header' ' + clean_fake_sendmail && + test_config mailmap.file "mailmap.test" && + cat >mailmap.test <<-EOF && + <someone@example.com> <someone@example.org> + EOF + git format-patch --stdout -1 --cc=someone@example.org >a.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --smtp-server="$(pwd)/fake.sendmail" \ + --mailmap \ + a.patch \ + 2>errors >out && + grep "^!someone@example\.com!$" commandline1 +' + test_expect_success $PREREQ 'test using command name with --sendmail-cmd' ' clean_fake_sendmail && PATH="$PWD:$PATH" \ diff --git a/t/t9002-column.sh b/t/t9002-column.sh index d5b98e615b..7353815c11 100755 --- a/t/t9002-column.sh +++ b/t/t9002-column.sh @@ -1,7 +1,6 @@ #!/bin/sh test_description='git column' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh index 14a704d0a8..85a5074b5e 100755 --- a/t/t9003-help-autocorrect.sh +++ b/t/t9003-help-autocorrect.sh @@ -2,7 +2,6 @@ test_description='help.autocorrect finding a match' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -65,7 +64,7 @@ test_expect_success 'autocorrect can be declined altogether' ' test_expect_success 'autocorrect works in work tree created from bare repo' ' git clone --bare . bare.git && git -C bare.git worktree add ../worktree && - git -C worktree -c help.autocorrect=immediate stauts + git -C worktree -c help.autocorrect=immediate status ' test_done diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index 52046e60d5..b2ee626b9a 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -21,32 +21,32 @@ a_empty_cr= a_empty_crlf= cd import - cat >> kw.c <<\EOF + cat >>kw.c <<\EOF /* Somebody prematurely put a keyword into this file */ /* $Id$ */ EOF - printf "Hello\r\nWorld\r\n" > crlf + printf "Hello\r\nWorld\r\n" >crlf a_crlf=$(git hash-object -w crlf) - printf "Hello\rWorld\r" > cr + printf "Hello\rWorld\r" >cr a_cr=$(git hash-object -w cr) - printf "Hello\nWorld\n" > lf + printf "Hello\nWorld\n" >lf a_lf=$(git hash-object -w lf) - printf "Hello\r\nWorld" > ne_crlf + printf "Hello\r\nWorld" >ne_crlf a_ne_crlf=$(git hash-object -w ne_crlf) - printf "Hello\nWorld" > ne_lf + printf "Hello\nWorld" >ne_lf a_ne_lf=$(git hash-object -w ne_lf) - printf "Hello\rWorld" > ne_cr + printf "Hello\rWorld" >ne_cr a_ne_cr=$(git hash-object -w ne_cr) touch empty a_empty=$(git hash-object -w empty) - printf "\n" > empty_lf + printf "\n" >empty_lf a_empty_lf=$(git hash-object -w empty_lf) - printf "\r" > empty_cr + printf "\r" >empty_cr a_empty_cr=$(git hash-object -w empty_cr) - printf "\r\n" > empty_crlf + printf "\r\n" >empty_crlf a_empty_crlf=$(git hash-object -w empty_crlf) svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null @@ -57,10 +57,10 @@ test_expect_success 'checkout working copy from svn' 'svn co "$svnrepo" test_wc' test_expect_success 'setup some commits to svn' ' ( cd test_wc && - echo Greetings >> kw.c && + echo Greetings >>kw.c && poke kw.c && svn_cmd commit -m "Not yet an Id" && - echo Hello world >> kw.c && + echo Hello world >>kw.c && poke kw.c && svn_cmd commit -m "Modified file, but still not yet an Id" && svn_cmd propset svn:keywords Id kw.c && @@ -75,7 +75,7 @@ test_expect_success 'fetch revisions from svn' 'git svn fetch' name='test svn:keywords ignoring' test_expect_success "$name" \ 'git checkout -b mybranch remotes/git-svn && - echo Hi again >> kw.c && + echo Hi again >>kw.c && git commit -a -m "test keywords ignoring" && git svn set-tree remotes/git-svn..mybranch && git pull . remotes/git-svn' @@ -106,8 +106,8 @@ done cd test_wc - printf '$Id$\rHello\rWorld\r' > cr - printf '$Id$\rHello\rWorld' > ne_cr + printf '$Id$\rHello\rWorld\r' >cr + printf '$Id$\rHello\rWorld' >ne_cr a_cr=$(printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin) a_ne_cr=$(printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin) test_expect_success 'Set CRLF on cr files' \ @@ -126,7 +126,7 @@ b_ne_cr="$(git hash-object ne_cr)" test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'" test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'" -cat > show-ignore.expect <<\EOF +cat >show-ignore.expect <<\EOF # / /no-such-file* @@ -153,7 +153,7 @@ no-such-file* ' . && svn_cmd commit -m 'propset svn:ignore' ) && - git svn show-ignore > show-ignore.got && + git svn show-ignore >show-ignore.got && cmp show-ignore.expect show-ignore.got " diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index 3d4842164c..a44eabf0d8 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -4,7 +4,6 @@ # test_description='Test export of commits to CVS' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq PERL; then diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index a41b4fcc08..027235d61a 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -169,6 +169,24 @@ test_expect_success 'scalar clone' ' ) ' +test_expect_success 'scalar clone --no-... opts' ' + # Note: redirect stderr always to avoid having a verbose test + # run result in a difference in the --[no-]progress option. + GIT_TRACE2_EVENT="$(pwd)/no-opt-trace" scalar clone \ + --no-tags --no-src \ + "file://$(pwd)" no-opts --single-branch 2>/dev/null && + + test_subcommand git fetch --quiet --no-progress \ + origin --no-tags <no-opt-trace && + ( + cd no-opts && + + test_cmp_config --no-tags remote.origin.tagopt && + git for-each-ref --format="%(refname)" refs/tags/ >tags && + test_line_count = 0 tags + ) +' + test_expect_success 'scalar reconfigure' ' git init one/src && scalar register one && @@ -176,8 +194,11 @@ test_expect_success 'scalar reconfigure' ' scalar reconfigure one && test true = "$(git -C one/src config core.preloadIndex)" && git -C one/src config core.preloadIndex false && - scalar reconfigure -a && - test true = "$(git -C one/src config core.preloadIndex)" + rm one/src/cron.txt && + GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && + test_path_is_file one/src/cron.txt && + test true = "$(git -C one/src config core.preloadIndex)" && + test_subcommand git maintenance start <reconfigure ' test_expect_success 'scalar reconfigure --all with includeIf.onbranch' ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 1e68426852..b258dbf1df 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -521,6 +521,113 @@ test_expect_success 'B: fail on invalid committer (5)' ' test_must_fail git fast-import <input ' +test_expect_success 'B: fail on invalid file path of ..' ' + cat >input <<-INPUT_END && + blob + mark :1 + data <<EOF + File contents + EOF + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Commit Message + COMMIT + M 100644 :1 ../invalid-path + INPUT_END + + test_when_finished "git update-ref -d refs/heads/badpath" && + test_must_fail git fast-import <input +' + +test_expect_success 'B: fail on invalid file path of .' ' + cat >input <<-INPUT_END && + blob + mark :1 + data <<EOF + File contents + EOF + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Good path + COMMIT + M 100644 :1 ok-path + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Bad path + COMMIT + R ok-path ./invalid-path + INPUT_END + + test_when_finished "git update-ref -d refs/heads/badpath" && + test_must_fail git fast-import <input +' + +test_expect_success WINDOWS 'B: fail on invalid file path of C:' ' + cat >input <<-INPUT_END && + blob + mark :1 + data <<EOF + File contents + EOF + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Commit Message + COMMIT + M 100644 :1 C:/invalid-path + INPUT_END + + test_when_finished "git update-ref -d refs/heads/badpath" && + test_must_fail git fast-import <input +' + +test_expect_success 'B: fail on invalid file path of .git' ' + cat >input <<-INPUT_END && + blob + mark :1 + data <<EOF + File contents + EOF + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Commit Message + COMMIT + M 100644 :1 .git/invalid-path + INPUT_END + + test_when_finished "git update-ref -d refs/heads/badpath" && + test_must_fail git fast-import <input +' + +test_expect_success 'B: fail on invalid file path of .gitmodules' ' + cat >input <<-INPUT_END && + blob + mark :1 + data <<EOF + File contents + EOF + + commit refs/heads/badpath + committer Name <email> $GIT_COMMITTER_DATE + data <<COMMIT + Commit Message + COMMIT + M 120000 :1 .gitmodules + INPUT_END + + test_when_finished "git update-ref -d refs/heads/badpath" && + test_must_fail git fast-import <input +' + ### ### series C ### @@ -945,7 +1052,7 @@ test_expect_success 'L: verify internal tree sorting' ' :100644 100644 M ba EXPECT_END - git fast-import <input && + git -c core.protectNTFS=false fast-import <input && GIT_PRINT_SHA1_ELLIPSIS="yes" git diff-tree --abbrev --raw L^ L >output && cut -d" " -f1,2,5 output >actual && test_cmp expect actual @@ -3096,7 +3203,7 @@ test_path_eol_success () { test_expect_success "S: paths at EOL with $test must work" ' test_when_finished "git branch -D S-path-eol" && - git fast-import --export-marks=marks.out <<-EOF >out 2>err && + git -c core.protectNTFS=false fast-import --export-marks=marks.out <<-EOF >out 2>err && blob mark :401 data <<BLOB @@ -3205,7 +3312,7 @@ test_path_space_success () { test_expect_success "S: paths before space with $test must work" ' test_when_finished "git branch -D S-path-space" && - git fast-import --export-marks=marks.out <<-EOF 2>err && + git -c core.protectNTFS=false fast-import --export-marks=marks.out <<-EOF 2>err && blob mark :401 data <<BLOB @@ -3675,7 +3782,7 @@ test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous thi ### series X (other new features) ### -test_expect_success 'X: handling encoding' ' +test_expect_success ICONV 'X: handling encoding' ' test_tick && cat >input <<-INPUT_END && commit refs/heads/encoding @@ -3691,6 +3798,34 @@ test_expect_success 'X: handling encoding' ' git log -1 --format=%B encoding | grep $(printf "\317\200") ' +test_expect_success 'X: replace ref that becomes useless is removed' ' + git init -qb main testrepo && + cd testrepo && + ( + test_commit test && + + test_commit msg somename content && + + git mv somename othername && + NEW_TREE=$(git write-tree) && + MSG="$(git log -1 --format=%B HEAD)" && + NEW_COMMIT=$(git commit-tree -p HEAD^1 -m "$MSG" $NEW_TREE) && + git replace main $NEW_COMMIT && + + echo more >>othername && + git add othername && + git commit -qm more && + + git fast-export --all >tmp && + sed -e s/othername/somename/ tmp >tmp2 && + git fast-import --force <tmp2 2>msgs && + + grep "Dropping.*since it would point to itself" msgs && + git show-ref >refs && + ! grep refs/replace refs + ) +' + ### ### series Y (submodules and hash algorithms) ### diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index 58413221e6..1ae4d7c0d3 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -7,7 +7,6 @@ test_description='test git fast-import of notes objects' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t9302-fast-import-unpack-limit.sh b/t/t9302-fast-import-unpack-limit.sh index d8b1f9442e..ec8c8652c6 100755 --- a/t/t9302-fast-import-unpack-limit.sh +++ b/t/t9302-fast-import-unpack-limit.sh @@ -1,7 +1,6 @@ #!/bin/sh test_description='test git fast-import unpack limit' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'create loose objects on import' ' diff --git a/t/t9303-fast-import-compression.sh b/t/t9303-fast-import-compression.sh index 4f5bf40587..f15c8c0213 100755 --- a/t/t9303-fast-import-compression.sh +++ b/t/t9303-fast-import-compression.sh @@ -2,7 +2,6 @@ test_description='compression setting of fast-import utility' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh import_large () { diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh index 410a871c52..6c50adca00 100755 --- a/t/t9304-fast-import-marks.sh +++ b/t/t9304-fast-import-marks.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='test exotic situations with marks' + . ./test-lib.sh test_expect_success 'setup dump of basic history' ' diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 1eb035ee4c..40427883ec 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -124,7 +124,7 @@ test_expect_success 'fast-export --show-original-ids | git fast-import' ' test $MUSS = $(git rev-parse --verify refs/tags/muss) ' -test_expect_success 'reencoding iso-8859-7' ' +test_expect_success ICONV 'reencoding iso-8859-7' ' test_when_finished "git reset --hard HEAD~1" && test_config i18n.commitencoding iso-8859-7 && @@ -420,7 +420,7 @@ M 100644 :1 there EOF -test_expect_success 'dropping tag of filtered out object' ' +test_expect_success ICONV 'dropping tag of filtered out object' ' ( cd limit-by-paths && git fast-export --tag-of-filtered-object=drop mytag -- there > output && @@ -437,7 +437,7 @@ msg EOF -test_expect_success 'rewriting tag of filtered out object' ' +test_expect_success ICONV 'rewriting tag of filtered out object' ' ( cd limit-by-paths && git fast-export --tag-of-filtered-object=rewrite mytag -- there > output && @@ -631,7 +631,7 @@ test_expect_success 'fast-export quotes pathnames' ' git rev-list HEAD >expect && git init result && cd result && - git fast-import <../export.out && + git -c core.protectNTFS=false fast-import <../export.out && git rev-list HEAD >actual && test_cmp ../expect actual ) @@ -666,7 +666,7 @@ M 100644 :13 file EOF -test_expect_success 'avoid uninteresting refs' ' +test_expect_success ICONV 'avoid uninteresting refs' ' > tmp-marks && git fast-export --import-marks=tmp-marks \ --export-marks=tmp-marks main > /dev/null && @@ -685,7 +685,7 @@ from :14 EOF -test_expect_success 'refs are updated even if no commits need to be exported' ' +test_expect_success ICONV 'refs are updated even if no commits need to be exported' ' > tmp-marks && git fast-export --import-marks=tmp-marks \ --export-marks=tmp-marks main > /dev/null && diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh index a67e6abd49..a34805acdc 100755 --- a/t/t9401-git-cvsserver-crlf.sh +++ b/t/t9401-git-cvsserver-crlf.sh @@ -12,7 +12,6 @@ repository using cvs CLI client via git-cvsserver server' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh marked_as () { diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index ccfa415384..7679780fb8 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -13,7 +13,6 @@ or warnings to log.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gitweb.sh # ---------------------------------------------------------------------- diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh index c900231079..32814e75df 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -13,7 +13,6 @@ code and message.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gitweb.sh # diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh index b41ea19331..81d5625557 100755 --- a/t/t9502-gitweb-standalone-parse-output.sh +++ b/t/t9502-gitweb-standalone-parse-output.sh @@ -13,7 +13,6 @@ in the HTTP header or the actual script output.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-gitweb.sh # ---------------------------------------------------------------------- diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh index 41fcf3606b..5680849218 100755 --- a/t/t9600-cvsimport.sh +++ b/t/t9600-cvsimport.sh @@ -4,7 +4,6 @@ test_description='git cvsimport basic tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-cvs.sh if ! test_have_prereq NOT_ROOT; then diff --git a/t/t9601-cvsimport-vendor-branch.sh b/t/t9601-cvsimport-vendor-branch.sh index e007669495..116cddba3a 100755 --- a/t/t9601-cvsimport-vendor-branch.sh +++ b/t/t9601-cvsimport-vendor-branch.sh @@ -35,7 +35,6 @@ test_description='git cvsimport handling of vendor branches' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-cvs.sh setup_cvs_test_repository t9601 diff --git a/t/t9602-cvsimport-branches-tags.sh b/t/t9602-cvsimport-branches-tags.sh index 3768e3bd8c..e5266c9a87 100755 --- a/t/t9602-cvsimport-branches-tags.sh +++ b/t/t9602-cvsimport-branches-tags.sh @@ -7,7 +7,6 @@ test_description='git cvsimport handling of branches and tags' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-cvs.sh setup_cvs_test_repository t9602 diff --git a/t/t9603-cvsimport-patchsets.sh b/t/t9603-cvsimport-patchsets.sh index 2a387fdbaa..1ee966c256 100755 --- a/t/t9603-cvsimport-patchsets.sh +++ b/t/t9603-cvsimport-patchsets.sh @@ -13,7 +13,6 @@ test_description='git cvsimport testing for correct patchset estimation' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-cvs.sh setup_cvs_test_repository t9603 diff --git a/t/t9604-cvsimport-timestamps.sh b/t/t9604-cvsimport-timestamps.sh index 9cf0685d56..57a3bef2ec 100755 --- a/t/t9604-cvsimport-timestamps.sh +++ b/t/t9604-cvsimport-timestamps.sh @@ -2,7 +2,6 @@ test_description='git cvsimport timestamps' -TEST_PASSES_SANITIZE_LEAK=true . ./lib-cvs.sh test_lazy_prereq POSIX_TIMEZONE ' diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh index ccc8212d73..9c9e3b5eb1 100755 --- a/t/t9700-perl-git.sh +++ b/t/t9700-perl-git.sh @@ -5,7 +5,6 @@ test_description='perl interface (Git.pm)' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-perl.sh @@ -45,7 +44,8 @@ test_expect_success 'set up test repository' ' ' test_expect_success 'set up bare repository' ' - git init --bare bare.git + git init --bare bare.git && + git -C bare.git --work-tree=. commit --allow-empty -m "bare commit" ' test_expect_success 'use t9700/test.pl to test Git.pm' ' diff --git a/t/t9700/test.pl b/t/t9700/test.pl index d8e85482ab..58a9b328d5 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl use lib (split(/:/, $ENV{GITPERLLIB})); -use 5.008001; +require v5.26; use warnings; use strict; @@ -147,6 +147,11 @@ close TEMPFILE3; unlink $tmpfile3; chdir($abs_repo_dir); +# open alternate bare repo +my $r4 = Git->repository(Directory => "$abs_repo_dir/bare.git"); +is($r4->command_oneline(qw(log --format=%s)), "bare commit", + "log of bare repo works"); + # unquoting paths is(Git::unquote_path('abc'), 'abc', 'unquote unquoted path'); is(Git::unquote_path('"abc def"'), 'abc def', 'unquote simple quoted path'); diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 53af8e34ac..0816763e46 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -297,8 +297,20 @@ test_expect_success 'exit when p4 fails to produce marshaled output' ' # p4 changes, files, or describe; just in p4 print. If P4CLIENT is unset, the # message will include "Librarian checkout". test_expect_success 'exit gracefully for p4 server errors' ' - test_when_finished "mv \"$db\"/depot/file1,v,hidden \"$db\"/depot/file1,v" && - mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden && + # Note that newer Perforce versions started to store files + # compressed in directories. The case statement handles both + # old and new layout. + case "$(echo "$db"/depot/file1*)" in + *,v) + test_when_finished "mv \"$db\"/depot/file1,v,hidden \"$db\"/depot/file1,v" && + mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden;; + *,d) + path="$(echo "$db"/depot/file1,d/*.gz)" && + test_when_finished "mv \"$path\",hidden \"$path\"" && + mv "$path" "$path",hidden;; + *) + BUG "unhandled p4d layout";; + esac && test_when_finished cleanup_git && test_expect_code 1 git p4 clone --dest="$git" //depot@1 >out 2>err && test_grep "Error from p4 print" err diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh index bb236cd2b5..df01a5d338 100755 --- a/t/t9802-git-p4-filetype.sh +++ b/t/t9802-git-p4-filetype.sh @@ -300,10 +300,22 @@ test_expect_success SYMLINKS 'empty symlink target' ' # text # @@ # + # Note that newer Perforce versions started to store files + # compressed in directories. The case statement handles both + # old and new layout. cd "$db/depot" && - sed "/@target1/{; s/target1/@/; n; d; }" \ - empty-symlink,v >empty-symlink,v.tmp && - mv empty-symlink,v.tmp empty-symlink,v + case "$(echo empty-symlink*)" in + empty-symlink,v) + sed "/@target1/{; s/target1/@/; n; d; }" \ + empty-symlink,v >empty-symlink,v.tmp && + mv empty-symlink,v.tmp empty-symlink,v;; + empty-symlink,d) + path="empty-symlink,d/$(ls empty-symlink,d/ | tail -n1)" && + rm "$path" && + gzip </dev/null >"$path";; + *) + BUG "unhandled p4d layout";; + esac ) && ( # Make sure symlink really is empty. Asking diff --git a/t/t9825-git-p4-handle-utf16-without-bom.sh b/t/t9825-git-p4-handle-utf16-without-bom.sh index f049ff8229..6a60b32349 100755 --- a/t/t9825-git-p4-handle-utf16-without-bom.sh +++ b/t/t9825-git-p4-handle-utf16-without-bom.sh @@ -22,9 +22,25 @@ test_expect_success 'init depot with UTF-16 encoded file and artificially remove cd db && p4d -jc && # P4D automatically adds a BOM. Remove it here to make the file invalid. - sed -e "\$d" depot/file1,v >depot/file1,v.new && - mv depot/file1,v.new depot/file1,v && - printf "@$UTF16@" >>depot/file1,v && + # + # Note that newer Perforce versions started to store files + # compressed in directories. The case statement handles both + # old and new layout. + case "$(echo depot/file1*)" in + depot/file1,v) + sed -e "\$d" depot/file1,v >depot/file1,v.new && + mv depot/file1,v.new depot/file1,v && + printf "@$UTF16@" >>depot/file1,v;; + depot/file1,d) + path="$(echo depot/file1,d/*.gz)" && + gunzip -c "$path" >"$path.unzipped" && + sed -e "\$d" "$path.unzipped" >"$path.new" && + printf "$UTF16" >>"$path.new" && + gzip -c "$path.new" >"$path" && + rm "$path.unzipped" "$path.new";; + *) + BUG "unhandled p4d layout";; + esac && p4d -jrF checkpoint.1 ) ' diff --git a/t/t9850-shell.sh b/t/t9850-shell.sh index cfc71c3bd4..36566ace21 100755 --- a/t/t9850-shell.sh +++ b/t/t9850-shell.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='git shell tests' + . ./test-lib.sh test_expect_success 'shell allows upload-pack' ' diff --git a/t/t9901-git-web--browse.sh b/t/t9901-git-web--browse.sh index 19f56e5680..de7152f827 100755 --- a/t/t9901-git-web--browse.sh +++ b/t/t9901-git-web--browse.sh @@ -5,7 +5,6 @@ test_description='git web--browse basic tests This test checks that git web--browse can handle various valid URLs.' -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_web_browse () { diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index cc6aa9f0cd..932d5ad759 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -16,7 +16,6 @@ test_untraceable=UnfortunatelyYes GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-bash.sh complete () diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 95e9955bca..d667dda654 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -8,7 +8,6 @@ test_description='test git-specific bash prompt functions' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME -TEST_PASSES_SANITIZE_LEAK=true . ./lib-bash.sh . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh" diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index fde9bf54fc..78e054ab50 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -926,7 +926,8 @@ test_expect_success () { test_body_or_stdin test_body "$2" test -n "$test_skip_test_preamble" || say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $test_body" - if test_run_ "$test_body" + if test_run_ "$test_body" && + check_test_results_san_file_empty_ then test_ok_ "$1" else diff --git a/t/test-lib.sh b/t/test-lib.sh index 54247604cb..426036b33a 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -322,7 +322,6 @@ TEST_RESULTS_SAN_FILE_PFX=trace TEST_RESULTS_SAN_DIR_SFX=leak TEST_RESULTS_SAN_FILE= TEST_RESULTS_SAN_DIR="$TEST_RESULTS_DIR/$TEST_NAME.$TEST_RESULTS_SAN_DIR_SFX" -TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP= TRASH_DIRECTORY="trash directory.$TEST_NAME$TEST_STRESS_JOB_SFX" test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY" case "$TRASH_DIRECTORY" in @@ -578,53 +577,6 @@ case $GIT_TEST_FSYNC in ;; esac -# Add libc MALLOC and MALLOC_PERTURB test only if we are not executing -# the test with valgrind and have not compiled with conflict SANITIZE -# options. -if test -n "$valgrind" || - test -n "$SANITIZE_ADDRESS" || - test -n "$SANITIZE_LEAK" || - test -n "$TEST_NO_MALLOC_CHECK" -then - setup_malloc_check () { - : nothing - } - teardown_malloc_check () { - : nothing - } -else - _USE_GLIBC_TUNABLES= - if _GLIBC_VERSION=$(getconf GNU_LIBC_VERSION 2>/dev/null) && - _GLIBC_VERSION=${_GLIBC_VERSION#"glibc "} && - expr 2.34 \<= "$_GLIBC_VERSION" >/dev/null - then - _USE_GLIBC_TUNABLES=YesPlease - fi - setup_malloc_check () { - local g - local t - MALLOC_CHECK_=3 MALLOC_PERTURB_=165 - export MALLOC_CHECK_ MALLOC_PERTURB_ - if test -n "$_USE_GLIBC_TUNABLES" - then - g= - LD_PRELOAD="libc_malloc_debug.so.0" - for t in \ - glibc.malloc.check=1 \ - glibc.malloc.perturb=165 - do - g="${g#:}:$t" - done - GLIBC_TUNABLES=$g - export LD_PRELOAD GLIBC_TUNABLES - fi - } - teardown_malloc_check () { - unset MALLOC_CHECK_ MALLOC_PERTURB_ - unset LD_PRELOAD GLIBC_TUNABLES - } -fi - # Protect ourselves from common misconfiguration to export # CDPATH into the environment unset CDPATH @@ -848,6 +800,7 @@ test_failure_ () { GIT_EXIT_OK=t exit 0 fi + check_test_results_san_file_ "$test_failure" _error_exit fi finalize_test_case_output failure "$failure_label" "$@" @@ -1215,61 +1168,19 @@ test_atexit_handler () { teardown_malloc_check } -sanitize_leak_log_message_ () { - local new="$1" && - local old="$2" && - local file="$3" && - - printf "With SANITIZE=leak at exit we have %d leak logs, but started with %d - -This means that we have a blindspot where git is leaking but we're -losing the exit code somewhere, or not propagating it appropriately -upwards! - -See the logs at \"%s.*\"; -those logs are reproduced below." \ - "$new" "$old" "$file" +check_test_results_san_file_empty_ () { + test -z "$TEST_RESULTS_SAN_FILE" || + test "$(nr_san_dir_leaks_)" = 0 } check_test_results_san_file_ () { - if test -z "$TEST_RESULTS_SAN_FILE" - then - return - fi && - local old="$TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP" && - local new="$(nr_san_dir_leaks_)" && - - if test $new -le $old + if check_test_results_san_file_empty_ then return fi && - local out="$(sanitize_leak_log_message_ "$new" "$old" "$TEST_RESULTS_SAN_FILE")" && - say_color error "$out" && - if test "$old" != 0 - then - echo && - say_color error "The logs include output from past runs to avoid" && - say_color error "that remove 'test-results' between runs." - fi && say_color error "$(cat "$TEST_RESULTS_SAN_FILE".*)" && - if test -n "$passes_sanitize_leak" && test "$test_failure" = 0 - then - say "As TEST_PASSES_SANITIZE_LEAK=true and our logs show we're leaking, exit non-zero!" && - invert_exit_code=t - elif test -n "$passes_sanitize_leak" - then - say "As TEST_PASSES_SANITIZE_LEAK=true and our logs show we're leaking, and we're failing for other reasons too..." && - invert_exit_code= - elif test -n "$sanitize_leak_check" && test "$test_failure" = 0 - then - say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" && - invert_exit_code= - elif test -n "$sanitize_leak_check" - then - say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" && - invert_exit_code=t - elif test "$test_failure" = 0 + if test "$test_failure" = 0 then say "Our logs revealed a memory leak, exit non-zero!" && invert_exit_code=t @@ -1300,11 +1211,6 @@ test_done () { EOF fi - if test -z "$passes_sanitize_leak" && test_bool_env TEST_PASSES_SANITIZE_LEAK false - then - BAIL_OUT "Please, set TEST_PASSES_SANITIZE_LEAK before sourcing test-lib.sh" - fi - if test "$test_fixed" != 0 then say_color error "# $test_fixed known breakage(s) vanished; please update test(s)" @@ -1509,6 +1415,56 @@ GIT_ATTR_NOSYSTEM=1 GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/.." export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM GIT_CEILING_DIRECTORIES +# Add libc MALLOC and MALLOC_PERTURB test only if we are not executing +# the test with valgrind and have not compiled with conflict SANITIZE +# options. +if test -n "$valgrind" || + test -n "$SANITIZE_ADDRESS" || + test -n "$SANITIZE_LEAK" || + test -n "$TEST_NO_MALLOC_CHECK" +then + setup_malloc_check () { + : nothing + } + teardown_malloc_check () { + : nothing + } +else + _USE_GLIBC_TUNABLES= + _USE_GLIBC_PRELOAD=libc_malloc_debug.so.0 + if _GLIBC_VERSION=$(getconf GNU_LIBC_VERSION 2>/dev/null) && + _GLIBC_VERSION=${_GLIBC_VERSION#"glibc "} && + expr 2.34 \<= "$_GLIBC_VERSION" >/dev/null && + stderr=$(LD_PRELOAD=$_USE_GLIBC_PRELOAD git version 2>&1 >/dev/null) && + test -z "$stderr" + then + _USE_GLIBC_TUNABLES=YesPlease + fi + setup_malloc_check () { + local g + local t + MALLOC_CHECK_=3 MALLOC_PERTURB_=165 + export MALLOC_CHECK_ MALLOC_PERTURB_ + if test -n "$_USE_GLIBC_TUNABLES" + then + g= + LD_PRELOAD=$_USE_GLIBC_PRELOAD + for t in \ + glibc.malloc.check=1 \ + glibc.malloc.perturb=165 + do + g="${g#:}:$t" + done + GLIBC_TUNABLES=$g + export LD_PRELOAD GLIBC_TUNABLES + fi + } + teardown_malloc_check () { + unset MALLOC_CHECK_ MALLOC_PERTURB_ + unset LD_PRELOAD GLIBC_TUNABLES + } +fi + if test -z "$GIT_TEST_CMP" then if test -n "$GIT_TEST_CMP_USE_COPIED_CONTEXT" @@ -1541,72 +1497,29 @@ then test_done fi -BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK () { - BAIL_OUT "$1 has no effect except when compiled with SANITIZE=leak" -} - if test -n "$SANITIZE_LEAK" then - # Normalize with test_bool_env - passes_sanitize_leak= - - # We need to see TEST_PASSES_SANITIZE_LEAK in "test-tool - # env-helper" (via test_bool_env) - export TEST_PASSES_SANITIZE_LEAK - if test_bool_env TEST_PASSES_SANITIZE_LEAK false - then - passes_sanitize_leak=t - fi - - if test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" - then - sanitize_leak_check=t - if test -n "$invert_exit_code" - then - BAIL_OUT "cannot use --invert-exit-code under GIT_TEST_PASSING_SANITIZE_LEAK=check" - fi - - if test -z "$passes_sanitize_leak" - then - say "in GIT_TEST_PASSING_SANITIZE_LEAK=check mode, setting --invert-exit-code for TEST_PASSES_SANITIZE_LEAK != true" - invert_exit_code=t - fi - elif test -z "$passes_sanitize_leak" && - test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false - then - skip_all="skipping $this_test under GIT_TEST_PASSING_SANITIZE_LEAK=true" - test_done - fi - + rm -rf "$TEST_RESULTS_SAN_DIR" if ! mkdir -p "$TEST_RESULTS_SAN_DIR" then BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR" fi && TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX" - # In case "test-results" is left over from a previous - # run: Only report if new leaks show up. - TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_) - # Don't litter *.leak dirs if there was nothing to report test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :" prepend_var LSAN_OPTIONS : dedup_token_length=9999 prepend_var LSAN_OPTIONS : log_exe_name=1 - prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\" + prepend_var LSAN_OPTIONS : log_path="'$TEST_RESULTS_SAN_FILE'" export LSAN_OPTIONS - -elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" || - test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false -then - BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true" fi if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 && test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0 then "$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" || - BUG "lint error (see '?!...!? annotations above)" + BUG "lint error (see 'LINT' annotations above)" fi # Last-minute variable setup @@ -1763,6 +1676,7 @@ esac ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1 test -z "$NO_CURL" && test_set_prereq LIBCURL +test -z "$NO_ICONV" && test_set_prereq ICONV test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PTHREADS" && test_set_prereq PTHREADS test -z "$NO_PYTHON" && test_set_prereq PYTHON diff --git a/t/test-terminal.perl b/t/test-terminal.perl index b8fd6a4f13..862bb8f395 100755 --- a/t/test-terminal.perl +++ b/t/test-terminal.perl @@ -1,5 +1,5 @@ #!/usr/bin/perl -use 5.008001; +require v5.26; use strict; use warnings; use IO::Pty; diff --git a/t/unit-tests/.gitignore b/t/unit-tests/.gitignore index 5e56e040ec..d0632ec7f9 100644 --- a/t/unit-tests/.gitignore +++ b/t/unit-tests/.gitignore @@ -1 +1,3 @@ /bin +/clar.suite +/clar-decls.h diff --git a/t/unit-tests/clar/.editorconfig b/t/unit-tests/clar/.editorconfig new file mode 100644 index 0000000000..aa343a4288 --- /dev/null +++ b/t/unit-tests/clar/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +insert_final_newline = true + +[*.{c,h}] +indent_style = tab +tab_width = 8 + +[CMakeLists.txt] +indent_style = tab +tab_width = 8 diff --git a/t/unit-tests/clar/.github/workflows/ci.yml b/t/unit-tests/clar/.github/workflows/ci.yml new file mode 100644 index 0000000000..0065843d17 --- /dev/null +++ b/t/unit-tests/clar/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + strategy: + matrix: + platform: + - os: ubuntu-latest + generator: Unix Makefiles + - os: macos-latest + generator: Unix Makefiles + - os: windows-latest + generator: Visual Studio 17 2022 + - os: windows-latest + generator: MSYS Makefiles + - os: windows-latest + generator: MinGW Makefiles + + runs-on: ${{ matrix.platform.os }} + + steps: + - name: Check out + uses: actions/checkout@v2 + - name: Build + run: | + mkdir build + cd build + cmake .. -G "${{matrix.platform.generator}}" + cmake --build . diff --git a/t/unit-tests/clar/.gitignore b/t/unit-tests/clar/.gitignore new file mode 100644 index 0000000000..84c048a73c --- /dev/null +++ b/t/unit-tests/clar/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/t/unit-tests/clar/CMakeLists.txt b/t/unit-tests/clar/CMakeLists.txt new file mode 100644 index 0000000000..12d4af114f --- /dev/null +++ b/t/unit-tests/clar/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.16..3.29) + +project(clar LANGUAGES C) + +option(BUILD_TESTS "Build test executable" ON) + +add_library(clar INTERFACE) +target_sources(clar INTERFACE + clar.c + clar.h + clar/fixtures.h + clar/fs.h + clar/print.h + clar/sandbox.h + clar/summary.h +) +set_target_properties(clar PROPERTIES + C_STANDARD 90 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF +) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) + if(BUILD_TESTING) + add_subdirectory(test) + endif() +endif() diff --git a/t/unit-tests/clar/COPYING b/t/unit-tests/clar/COPYING new file mode 100644 index 0000000000..8983817f0c --- /dev/null +++ b/t/unit-tests/clar/COPYING @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2011-2015 Vicent Marti + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/t/unit-tests/clar/README.md b/t/unit-tests/clar/README.md new file mode 100644 index 0000000000..a8961c5f10 --- /dev/null +++ b/t/unit-tests/clar/README.md @@ -0,0 +1,329 @@ +Come out and Clar +================= + +In Catalan, "clar" means clear, easy to perceive. Using clar will make it +easy to test and make clear the quality of your code. + +> _Historical note_ +> +> Originally the clar project was named "clay" because the word "test" has its +> roots in the latin word *"testum"*, meaning "earthen pot", and *"testa"*, +> meaning "piece of burned clay"? +> +> This is because historically, testing implied melting metal in a pot to +> check its quality. Clay is what tests are made of. + +## Quick Usage Overview + +Clar is a minimal C unit testing framework. It's been written to replace the +old framework in [libgit2][libgit2], but it's both very versatile and +straightforward to use. + +Can you count to funk? + +- **Zero: Initialize test directory** + + ~~~~ sh + $ mkdir tests + $ cp -r $CLAR_ROOT/clar* tests + $ cp $CLAR_ROOT/test/clar_test.h tests + $ cp $CLAR_ROOT/test/main.c.sample tests/main.c + ~~~~ + +- **One: Write some tests** + + File: tests/adding.c: + + ~~~~ c + /* adding.c for the "Adding" suite */ + #include "clar.h" + + static int *answer; + + void test_adding__initialize(void) + { + answer = malloc(sizeof(int)); + cl_assert_(answer != NULL, "No memory left?"); + *answer = 42; + } + + void test_adding__cleanup(void) + { + free(answer); + } + + void test_adding__make_sure_math_still_works(void) + { + cl_assert_(5 > 3, "Five should probably be greater than three"); + cl_assert_(-5 < 2, "Negative numbers are small, I think"); + cl_assert_(*answer == 42, "The universe is doing OK. And the initializer too."); + } + ~~~~~ + +- **Two: Build the test executable** + + ~~~~ sh + $ cd tests + $ $CLAR_PATH/generate.py . + Written `clar.suite` (1 suites) + $ gcc -I. clar.c main.c adding.c -o testit + ~~~~ + +- **Funk: Funk it.** + + ~~~~ sh + $ ./testit + ~~~~ + +## The Clar Test Suite + +Writing a test suite is pretty straightforward. Each test suite is a `*.c` +file with a descriptive name: this encourages modularity. + +Each test suite has optional initialize and cleanup methods. These methods +will be called before and after running **each** test in the suite, even if +such test fails. As a rule of thumb, if a test needs a different initializer +or cleanup method than another test in the same module, that means it +doesn't belong in that module. Keep that in mind when grouping tests +together. + +The `initialize` and `cleanup` methods have the following syntax, with +`suitename` being the current suite name, e.g. `adding` for the `adding.c` +suite. + +~~~~ c +void test_suitename__initialize(void) +{ + /* init */ +} + +void test_suitename__cleanup(void) +{ + /* cleanup */ +} +~~~~ + +These methods are encouraged to use static, global variables to store the state +that will be used by all tests inside the suite. + +~~~~ c +static git_repository *_repository; + +void test_status__initialize(void) +{ + create_tmp_repo(STATUS_REPO); + git_repository_open(_repository, STATUS_REPO); +} + +void test_status__cleanup(void) +{ + git_repository_close(_repository); + git_path_rm(STATUS_REPO); +} + +void test_status__simple_test(void) +{ + /* do something with _repository */ +} +~~~~ + +Writing the actual tests is just as straightforward. Tests have the +`void test_suitename__test_name(void)` signature, and they should **not** +be static. Clar will automatically detect and list them. + +Tests are run as they appear on their original suites: they have no return +value. A test is considered "passed" if it doesn't raise any errors. Check +the "Clar API" section to see the various helper functions to check and +raise errors during test execution. + +__Caution:__ If you use assertions inside of `test_suitename__initialize`, +make sure that you do not rely on `__initialize` being completely run +inside your `test_suitename__cleanup` function. Otherwise you might +encounter ressource cleanup twice. + +## How does Clar work? + +To use Clar: + +1. copy the Clar boilerplate to your test directory +2. copy (and probably modify) the sample `main.c` (from + `$CLAR_PATH/test/main.c.sample`) +3. run the Clar mixer (a.k.a. `generate.py`) to scan your test directory and + write out the test suite metadata. +4. compile your test files and the Clar boilerplate into a single test + executable +5. run the executable to test! + +The Clar boilerplate gives you a set of useful test assertions and features +(like accessing or making sandbox copies of fixture data). It consists of +the `clar.c` and `clar.h` files, plus the code in the `clar/` subdirectory. +You should not need to edit these files. + +The sample `main.c` (i.e. `$CLAR_PATH/test/main.c.sample`) file invokes +`clar_test(argc, argv)` to run the tests. Usually, you will edit this file +to perform any framework specific initialization and teardown that you need. + +The Clar mixer (`generate.py`) recursively scans your test directory for +any `.c` files, parses them, and writes the `clar.suite` file with all of +the metadata about your tests. When you build, the `clar.suite` file is +included into `clar.c`. + +The mixer can be run with **Python 2.5, 2.6, 2.7, 3.0, 3.1, 3.2 and PyPy 1.6**. + +Commandline usage of the mixer is as follows: + + $ ./generate.py . + +Where `.` is the folder where all the test suites can be found. The mixer +will automatically locate all the relevant source files and build the +testing metadata. The metadata will be written to `clar.suite`, in the same +folder as all the test suites. This file is included by `clar.c` and so +must be accessible via `#include` when building the test executable. + + $ gcc -I. clar.c main.c suite1.c test2.c -o run_tests + +**Note that the Clar mixer only needs to be ran when adding new tests to a +suite, in order to regenerate the metadata**. As a result, the `clar.suite` +file can be checked into version control if you wish to be able to build +your test suite without having to re-run the mixer. + +This is handy when e.g. generating tests in a local computer, and then +building and testing them on an embedded device or a platform where Python +is not available. + +### Fixtures + +Clar can create sandboxed fixtures for you to use in your test. You'll need to compile *clar.c* with an additional `CFLAG`, `-DCLAR_FIXTURE_PATH`. This should be an absolute path to your fixtures directory. + +Once that's done, you can use the fixture API as defined below. + +## The Clar API + +Clar makes the following methods available from all functions in a test +suite. + +- `cl_must_pass(call)`, `cl_must_pass_(call, message)`: Verify that the given + function call passes, in the POSIX sense (returns a value greater or equal + to 0). + +- `cl_must_fail(call)`, `cl_must_fail_(call, message)`: Verify that the given + function call fails, in the POSIX sense (returns a value less than 0). + +- `cl_assert(expr)`, `cl_assert_(expr, message)`: Verify that `expr` is true. + +- `cl_check_pass(call)`, `cl_check_pass_(call, message)`: Verify that the + given function call passes, in the POSIX sense (returns a value greater or + equal to 0). If the function call doesn't succeed, a test failure will be + logged but the test's execution will continue. + +- `cl_check_fail(call)`, `cl_check_fail_(call, message)`: Verify that the + given function call fails, in the POSIX sense (returns a value less than + 0). If the function call doesn't fail, a test failure will be logged but + the test's execution will continue. + +- `cl_check(expr)`: Verify that `expr` is true. If `expr` is not + true, a test failure will be logged but the test's execution will continue. + +- `cl_fail(message)`: Fail the current test with the given message. + +- `cl_warning(message)`: Issue a warning. This warning will be + logged as a test failure but the test's execution will continue. + +- `cl_set_cleanup(void (*cleanup)(void *), void *opaque)`: Set the cleanup + method for a single test. This method will be called with `opaque` as its + argument before the test returns (even if the test has failed). + If a global cleanup method is also available, the local cleanup will be + called first, and then the global. + +- `cl_assert_equal_i(int,int)`: Verify that two integer values are equal. + The advantage of this over a simple `cl_assert` is that it will format + a much nicer error report if the values are not equal. + +- `cl_assert_equal_s(const char *,const char *)`: Verify that two strings + are equal. The expected value can also be NULL and this will correctly + test for that. + +- `cl_fixture_sandbox(const char *)`: Sets up a sandbox for a fixture + so that you can mutate the file directly. + +- `cl_fixture_cleanup(const char *)`: Tears down the previous fixture + sandbox. + +- `cl_fixture(const char *)`: Gets the full path to a fixture file. + +Please do note that these methods are *always* available whilst running a +test, even when calling auxiliary/static functions inside the same file. + +It's strongly encouraged to perform test assertions in auxiliary methods, +instead of returning error values. This is considered good Clar style. + +Style Example: + +~~~~ c +/* + * Bad style: auxiliary functions return an error code + */ + +static int check_string(const char *str) +{ + const char *aux = process_string(str); + + if (aux == NULL) + return -1; + + return strcmp(my_function(aux), str) == 0 ? 0 : -1; +} + +void test_example__a_test_with_auxiliary_methods(void) +{ + cl_must_pass_( + check_string("foo"), + "String differs after processing" + ); + + cl_must_pass_( + check_string("bar"), + "String differs after processing" + ); +} +~~~~ + +~~~~ c +/* + * Good style: auxiliary functions perform assertions + */ + +static void check_string(const char *str) +{ + const char *aux = process_string(str); + + cl_assert_( + aux != NULL, + "String processing failed" + ); + + cl_assert_( + strcmp(my_function(aux), str) == 0, + "String differs after processing" + ); +} + +void test_example__a_test_with_auxiliary_methods(void) +{ + check_string("foo"); + check_string("bar"); +} +~~~~ + +About Clar +========== + +Clar has been written from scratch by [Vicent MartÃ](https://github.com/vmg), +to replace the old testing framework in [libgit2][libgit2]. + +Do you know what languages are *in* on the SF startup scene? Node.js *and* +Latin. Follow [@vmg](https://www.twitter.com/vmg) on Twitter to +receive more lessons on word etymology. You can be hip too. + + +[libgit2]: https://github.com/libgit2/libgit2 diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c new file mode 100644 index 0000000000..d54e455367 --- /dev/null +++ b/t/unit-tests/clar/clar.c @@ -0,0 +1,857 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ + +#define _BSD_SOURCE +#define _DARWIN_C_SOURCE +#define _DEFAULT_SOURCE + +#include <errno.h> +#include <setjmp.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdarg.h> +#include <wchar.h> +#include <time.h> +#include <inttypes.h> + +/* required for sandboxing */ +#include <sys/types.h> +#include <sys/stat.h> + +#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_WCHAR__) + /* + * uClibc can optionally be built without wchar support, in which case + * the installed <wchar.h> is a stub that only defines the `whar_t` + * type but none of the functions typically declared by it. + */ +#else +# define CLAR_HAVE_WCHAR +#endif + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include <io.h> +# include <direct.h> + +# define _MAIN_CC __cdecl + +# ifndef stat +# define stat(path, st) _stat(path, st) + typedef struct _stat STAT_T; +# else + typedef struct stat STAT_T; +# endif +# ifndef mkdir +# define mkdir(path, mode) _mkdir(path) +# endif +# ifndef chdir +# define chdir(path) _chdir(path) +# endif +# ifndef access +# define access(path, mode) _access(path, mode) +# endif +# ifndef strdup +# define strdup(str) _strdup(str) +# endif +# ifndef strcasecmp +# define strcasecmp(a,b) _stricmp(a,b) +# endif + +# ifndef __MINGW32__ +# pragma comment(lib, "shell32") +# ifndef strncpy +# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) +# endif +# ifndef W_OK +# define W_OK 02 +# endif +# ifndef S_ISDIR +# define S_ISDIR(x) ((x & _S_IFDIR) != 0) +# endif +# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) +# else +# define p_snprintf snprintf +# endif +#else +# include <sys/wait.h> /* waitpid(2) */ +# include <unistd.h> +# define _MAIN_CC +# define p_snprintf snprintf + typedef struct stat STAT_T; +#endif + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#include "clar.h" + +static void fs_rm(const char *_source); +static void fs_copy(const char *_source, const char *dest); + +#ifdef CLAR_FIXTURE_PATH +static const char * +fixture_path(const char *base, const char *fixture_name); +#endif + +struct clar_error { + const char *file; + const char *function; + uintmax_t line_number; + const char *error_msg; + char *description; + + struct clar_error *next; +}; + +struct clar_explicit { + size_t suite_idx; + const char *filter; + + struct clar_explicit *next; +}; + +struct clar_report { + const char *test; + int test_number; + const char *suite; + + enum cl_test_status status; + time_t start; + double elapsed; + + struct clar_error *errors; + struct clar_error *last_error; + + struct clar_report *next; +}; + +struct clar_summary { + const char *filename; + FILE *fp; +}; + +static struct { + enum cl_test_status test_status; + + const char *active_test; + const char *active_suite; + + int total_skipped; + int total_errors; + + int tests_ran; + int suites_ran; + + enum cl_output_format output_format; + + int report_errors_only; + int exit_on_error; + int verbosity; + + int write_summary; + char *summary_filename; + struct clar_summary *summary; + + struct clar_explicit *explicit; + struct clar_explicit *last_explicit; + + struct clar_report *reports; + struct clar_report *last_report; + + void (*local_cleanup)(void *); + void *local_cleanup_payload; + + jmp_buf trampoline; + int trampoline_enabled; + + cl_trace_cb *pfn_trace_cb; + void *trace_payload; + +} _clar; + +struct clar_func { + const char *name; + void (*ptr)(void); +}; + +struct clar_suite { + const char *name; + struct clar_func initialize; + struct clar_func cleanup; + const struct clar_func *tests; + size_t test_count; + int enabled; +}; + +/* From clar_print_*.c */ +static void clar_print_init(int test_count, int suite_count, const char *suite_names); +static void clar_print_shutdown(int test_count, int suite_count, int error_count); +static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error); +static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed); +static void clar_print_onsuite(const char *suite_name, int suite_index); +static void clar_print_onabortv(const char *msg, va_list argp); +static void clar_print_onabort(const char *msg, ...); + +/* From clar_sandbox.c */ +static void clar_unsandbox(void); +static void clar_sandbox(void); + +/* From summary.h */ +static struct clar_summary *clar_summary_init(const char *filename); +static int clar_summary_shutdown(struct clar_summary *fp); + +/* Load the declarations for the test suite */ +#include "clar.suite" + + +#define CL_TRACE(ev) \ + do { \ + if (_clar.pfn_trace_cb) \ + _clar.pfn_trace_cb(ev, \ + _clar.active_suite, \ + _clar.active_test, \ + _clar.trace_payload); \ + } while (0) + +static void clar_abort(const char *msg, ...) +{ + va_list argp; + va_start(argp, msg); + clar_print_onabortv(msg, argp); + va_end(argp); + exit(-1); +} + +void cl_trace_register(cl_trace_cb *cb, void *payload) +{ + _clar.pfn_trace_cb = cb; + _clar.trace_payload = payload; +} + + +/* Core test functions */ +static void +clar_report_errors(struct clar_report *report) +{ + struct clar_error *error; + int i = 1; + + for (error = report->errors; error; error = error->next) + clar_print_error(i++, _clar.last_report, error); +} + +static void +clar_report_all(void) +{ + struct clar_report *report; + struct clar_error *error; + int i = 1; + + for (report = _clar.reports; report; report = report->next) { + if (report->status != CL_TEST_FAILURE) + continue; + + for (error = report->errors; error; error = error->next) + clar_print_error(i++, report, error); + } +} + +#ifdef WIN32 +# define clar_time DWORD + +static void clar_time_now(clar_time *out) +{ + *out = GetTickCount(); +} + +static double clar_time_diff(clar_time *start, clar_time *end) +{ + return ((double)*end - (double)*start) / 1000; +} +#else +# include <sys/time.h> + +# define clar_time struct timeval + +static void clar_time_now(clar_time *out) +{ + gettimeofday(out, NULL); +} + +static double clar_time_diff(clar_time *start, clar_time *end) +{ + return ((double)end->tv_sec + (double)end->tv_usec / 1.0E6) - + ((double)start->tv_sec + (double)start->tv_usec / 1.0E6); +} +#endif + +static void +clar_run_test( + const struct clar_suite *suite, + const struct clar_func *test, + const struct clar_func *initialize, + const struct clar_func *cleanup) +{ + clar_time start, end; + + _clar.trampoline_enabled = 1; + + CL_TRACE(CL_TRACE__TEST__BEGIN); + + _clar.last_report->start = time(NULL); + clar_time_now(&start); + + if (setjmp(_clar.trampoline) == 0) { + if (initialize->ptr != NULL) + initialize->ptr(); + + CL_TRACE(CL_TRACE__TEST__RUN_BEGIN); + test->ptr(); + CL_TRACE(CL_TRACE__TEST__RUN_END); + } + + clar_time_now(&end); + + _clar.trampoline_enabled = 0; + + if (_clar.last_report->status == CL_TEST_NOTRUN) + _clar.last_report->status = CL_TEST_OK; + + _clar.last_report->elapsed = clar_time_diff(&start, &end); + + if (_clar.local_cleanup != NULL) + _clar.local_cleanup(_clar.local_cleanup_payload); + + if (cleanup->ptr != NULL) + cleanup->ptr(); + + CL_TRACE(CL_TRACE__TEST__END); + + _clar.tests_ran++; + + /* remove any local-set cleanup methods */ + _clar.local_cleanup = NULL; + _clar.local_cleanup_payload = NULL; + + if (_clar.report_errors_only) { + clar_report_errors(_clar.last_report); + } else { + clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status); + } +} + +static void +clar_run_suite(const struct clar_suite *suite, const char *filter) +{ + const struct clar_func *test = suite->tests; + size_t i, matchlen; + struct clar_report *report; + int exact = 0; + + if (!suite->enabled) + return; + + if (_clar.exit_on_error && _clar.total_errors) + return; + + if (!_clar.report_errors_only) + clar_print_onsuite(suite->name, ++_clar.suites_ran); + + _clar.active_suite = suite->name; + _clar.active_test = NULL; + CL_TRACE(CL_TRACE__SUITE_BEGIN); + + if (filter) { + size_t suitelen = strlen(suite->name); + matchlen = strlen(filter); + if (matchlen <= suitelen) { + filter = NULL; + } else { + filter += suitelen; + while (*filter == ':') + ++filter; + matchlen = strlen(filter); + + if (matchlen && filter[matchlen - 1] == '$') { + exact = 1; + matchlen--; + } + } + } + + for (i = 0; i < suite->test_count; ++i) { + if (filter && strncmp(test[i].name, filter, matchlen)) + continue; + + if (exact && strlen(test[i].name) != matchlen) + continue; + + _clar.active_test = test[i].name; + + if ((report = calloc(1, sizeof(*report))) == NULL) + clar_abort("Failed to allocate report.\n"); + report->suite = _clar.active_suite; + report->test = _clar.active_test; + report->test_number = _clar.tests_ran; + report->status = CL_TEST_NOTRUN; + + if (_clar.reports == NULL) + _clar.reports = report; + + if (_clar.last_report != NULL) + _clar.last_report->next = report; + + _clar.last_report = report; + + clar_run_test(suite, &test[i], &suite->initialize, &suite->cleanup); + + if (_clar.exit_on_error && _clar.total_errors) + return; + } + + _clar.active_test = NULL; + CL_TRACE(CL_TRACE__SUITE_END); +} + +static void +clar_usage(const char *arg) +{ + printf("Usage: %s [options]\n\n", arg); + printf("Options:\n"); + printf(" -sname Run only the suite with `name` (can go to individual test name)\n"); + printf(" -iname Include the suite with `name`\n"); + printf(" -xname Exclude the suite with `name`\n"); + printf(" -v Increase verbosity (show suite names)\n"); + printf(" -q Only report tests that had an error\n"); + printf(" -Q Quit as soon as a test fails\n"); + printf(" -t Display results in tap format\n"); + printf(" -l Print suite names\n"); + printf(" -r[filename] Write summary file (to the optional filename)\n"); + exit(-1); +} + +static void +clar_parse_args(int argc, char **argv) +{ + int i; + + /* Verify options before execute */ + for (i = 1; i < argc; ++i) { + char *argument = argv[i]; + + if (argument[0] != '-' || argument[1] == '\0' + || strchr("sixvqQtlr", argument[1]) == NULL) { + clar_usage(argv[0]); + } + } + + for (i = 1; i < argc; ++i) { + char *argument = argv[i]; + + switch (argument[1]) { + case 's': + case 'i': + case 'x': { /* given suite name */ + int offset = (argument[2] == '=') ? 3 : 2, found = 0; + char action = argument[1]; + size_t j, arglen, suitelen, cmplen; + + argument += offset; + arglen = strlen(argument); + + if (arglen == 0) + clar_usage(argv[0]); + + for (j = 0; j < _clar_suite_count; ++j) { + suitelen = strlen(_clar_suites[j].name); + cmplen = (arglen < suitelen) ? arglen : suitelen; + + if (strncmp(argument, _clar_suites[j].name, cmplen) == 0) { + int exact = (arglen >= suitelen); + + /* Do we have a real suite prefix separated by a + * trailing '::' or just a matching substring? */ + if (arglen > suitelen && (argument[suitelen] != ':' + || argument[suitelen + 1] != ':')) + continue; + + ++found; + + if (!exact) + _clar.verbosity = MAX(_clar.verbosity, 1); + + switch (action) { + case 's': { + struct clar_explicit *explicit; + + if ((explicit = calloc(1, sizeof(*explicit))) == NULL) + clar_abort("Failed to allocate explicit test.\n"); + + explicit->suite_idx = j; + explicit->filter = argument; + + if (_clar.explicit == NULL) + _clar.explicit = explicit; + + if (_clar.last_explicit != NULL) + _clar.last_explicit->next = explicit; + + _clar_suites[j].enabled = 1; + _clar.last_explicit = explicit; + break; + } + case 'i': _clar_suites[j].enabled = 1; break; + case 'x': _clar_suites[j].enabled = 0; break; + } + + if (exact) + break; + } + } + + if (!found) + clar_abort("No suite matching '%s' found.\n", argument); + break; + } + + case 'q': + _clar.report_errors_only = 1; + break; + + case 'Q': + _clar.exit_on_error = 1; + break; + + case 't': + _clar.output_format = CL_OUTPUT_TAP; + break; + + case 'l': { + size_t j; + printf("Test suites (use -s<name> to run just one):\n"); + for (j = 0; j < _clar_suite_count; ++j) + printf(" %3d: %s\n", (int)j, _clar_suites[j].name); + + exit(0); + } + + case 'v': + _clar.verbosity++; + break; + + case 'r': + _clar.write_summary = 1; + free(_clar.summary_filename); + if (*(argument + 2)) { + if ((_clar.summary_filename = strdup(argument + 2)) == NULL) + clar_abort("Failed to allocate summary filename.\n"); + } else { + _clar.summary_filename = NULL; + } + break; + + default: + clar_abort("Unexpected commandline argument '%s'.\n", + argument[1]); + } + } +} + +void +clar_test_init(int argc, char **argv) +{ + const char *summary_env; + + if (argc > 1) + clar_parse_args(argc, argv); + + clar_print_init( + (int)_clar_callback_count, + (int)_clar_suite_count, + "" + ); + + if (!_clar.summary_filename && + (summary_env = getenv("CLAR_SUMMARY")) != NULL) { + _clar.write_summary = 1; + if ((_clar.summary_filename = strdup(summary_env)) == NULL) + clar_abort("Failed to allocate summary filename.\n"); + } + + if (_clar.write_summary && !_clar.summary_filename) + if ((_clar.summary_filename = strdup("summary.xml")) == NULL) + clar_abort("Failed to allocate summary filename.\n"); + + if (_clar.write_summary) + _clar.summary = clar_summary_init(_clar.summary_filename); + + clar_sandbox(); +} + +int +clar_test_run(void) +{ + size_t i; + struct clar_explicit *explicit; + + if (_clar.explicit) { + for (explicit = _clar.explicit; explicit; explicit = explicit->next) + clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter); + } else { + for (i = 0; i < _clar_suite_count; ++i) + clar_run_suite(&_clar_suites[i], NULL); + } + + return _clar.total_errors; +} + +void +clar_test_shutdown(void) +{ + struct clar_explicit *explicit, *explicit_next; + struct clar_report *report, *report_next; + + clar_print_shutdown( + _clar.tests_ran, + (int)_clar_suite_count, + _clar.total_errors + ); + + clar_unsandbox(); + + if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) + clar_abort("Failed to write the summary file '%s: %s.\n", + _clar.summary_filename, strerror(errno)); + + for (explicit = _clar.explicit; explicit; explicit = explicit_next) { + explicit_next = explicit->next; + free(explicit); + } + + for (report = _clar.reports; report; report = report_next) { + report_next = report->next; + free(report); + } + + free(_clar.summary_filename); +} + +int +clar_test(int argc, char **argv) +{ + int errors; + + clar_test_init(argc, argv); + errors = clar_test_run(); + clar_test_shutdown(); + + return errors; +} + +static void abort_test(void) +{ + if (!_clar.trampoline_enabled) { + clar_print_onabort( + "Fatal error: a cleanup method raised an exception.\n"); + clar_report_errors(_clar.last_report); + exit(-1); + } + + CL_TRACE(CL_TRACE__TEST__LONGJMP); + longjmp(_clar.trampoline, -1); +} + +void clar__skip(void) +{ + _clar.last_report->status = CL_TEST_SKIP; + _clar.total_skipped++; + abort_test(); +} + +void clar__fail( + const char *file, + const char *function, + size_t line, + const char *error_msg, + const char *description, + int should_abort) +{ + struct clar_error *error; + + if ((error = calloc(1, sizeof(*error))) == NULL) + clar_abort("Failed to allocate error.\n"); + + if (_clar.last_report->errors == NULL) + _clar.last_report->errors = error; + + if (_clar.last_report->last_error != NULL) + _clar.last_report->last_error->next = error; + + _clar.last_report->last_error = error; + + error->file = file; + error->function = function; + error->line_number = line; + error->error_msg = error_msg; + + if (description != NULL && + (error->description = strdup(description)) == NULL) + clar_abort("Failed to allocate description.\n"); + + _clar.total_errors++; + _clar.last_report->status = CL_TEST_FAILURE; + + if (should_abort) + abort_test(); +} + +void clar__assert( + int condition, + const char *file, + const char *function, + size_t line, + const char *error_msg, + const char *description, + int should_abort) +{ + if (condition) + return; + + clar__fail(file, function, line, error_msg, description, should_abort); +} + +void clar__assert_equal( + const char *file, + const char *function, + size_t line, + const char *err, + int should_abort, + const char *fmt, + ...) +{ + va_list args; + char buf[4096]; + int is_equal = 1; + + va_start(args, fmt); + + if (!strcmp("%s", fmt)) { + const char *s1 = va_arg(args, const char *); + const char *s2 = va_arg(args, const char *); + is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2); + + if (!is_equal) { + if (s1 && s2) { + int pos; + for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)", + s1, s2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2); + } + } + } + else if(!strcmp("%.*s", fmt)) { + const char *s1 = va_arg(args, const char *); + const char *s2 = va_arg(args, const char *); + int len = va_arg(args, int); + is_equal = (!s1 || !s2) ? (s1 == s2) : !strncmp(s1, s2, len); + + if (!is_equal) { + if (s1 && s2) { + int pos; + for (pos = 0; s1[pos] == s2[pos] && pos < len; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s' (at byte %d)", + len, s1, len, s2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s'", len, s1, len, s2); + } + } + } +#ifdef CLAR_HAVE_WCHAR + else if (!strcmp("%ls", fmt)) { + const wchar_t *wcs1 = va_arg(args, const wchar_t *); + const wchar_t *wcs2 = va_arg(args, const wchar_t *); + is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcscmp(wcs1, wcs2); + + if (!is_equal) { + if (wcs1 && wcs2) { + int pos; + for (pos = 0; wcs1[pos] == wcs2[pos] && wcs1[pos] && wcs2[pos]; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%ls' != '%ls' (at byte %d)", + wcs1, wcs2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%ls' != '%ls'", wcs1, wcs2); + } + } + } + else if(!strcmp("%.*ls", fmt)) { + const wchar_t *wcs1 = va_arg(args, const wchar_t *); + const wchar_t *wcs2 = va_arg(args, const wchar_t *); + int len = va_arg(args, int); + is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcsncmp(wcs1, wcs2, len); + + if (!is_equal) { + if (wcs1 && wcs2) { + int pos; + for (pos = 0; wcs1[pos] == wcs2[pos] && pos < len; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls' (at byte %d)", + len, wcs1, len, wcs2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls'", len, wcs1, len, wcs2); + } + } + } +#endif /* CLAR_HAVE_WCHAR */ + else if (!strcmp("%"PRIuMAX, fmt) || !strcmp("%"PRIxMAX, fmt)) { + uintmax_t sz1 = va_arg(args, uintmax_t), sz2 = va_arg(args, uintmax_t); + is_equal = (sz1 == sz2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2); + } + } + else if (!strcmp("%p", fmt)) { + void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *); + is_equal = (p1 == p2); + if (!is_equal) + p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2); + } + else { + int i1 = va_arg(args, int), i2 = va_arg(args, int); + is_equal = (i1 == i2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, i1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2); + } + } + + va_end(args); + + if (!is_equal) + clar__fail(file, function, line, err, buf, should_abort); +} + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque) +{ + _clar.local_cleanup = cleanup; + _clar.local_cleanup_payload = opaque; +} + +#include "clar/sandbox.h" +#include "clar/fixtures.h" +#include "clar/fs.h" +#include "clar/print.h" +#include "clar/summary.h" diff --git a/t/unit-tests/clar/clar.h b/t/unit-tests/clar/clar.h new file mode 100644 index 0000000000..8c22382bd5 --- /dev/null +++ b/t/unit-tests/clar/clar.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ +#ifndef __CLAR_TEST_H__ +#define __CLAR_TEST_H__ + +#include <stdlib.h> + +enum cl_test_status { + CL_TEST_OK, + CL_TEST_FAILURE, + CL_TEST_SKIP, + CL_TEST_NOTRUN, +}; + +enum cl_output_format { + CL_OUTPUT_CLAP, + CL_OUTPUT_TAP, +}; + +/** Setup clar environment */ +void clar_test_init(int argc, char *argv[]); +int clar_test_run(void); +void clar_test_shutdown(void); + +/** One shot setup & run */ +int clar_test(int argc, char *argv[]); + +const char *clar_sandbox_path(void); + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque); +void cl_fs_cleanup(void); + +/** + * cl_trace_* is a hook to provide a simple global tracing + * mechanism. + * + * The goal here is to let main() provide clar-proper + * with a callback to optionally write log info for + * test operations into the same stream used by their + * actual tests. This would let them print test names + * and maybe performance data as they choose. + * + * The goal is NOT to alter the flow of control or to + * override test selection/skipping. (So the callback + * does not return a value.) + * + * The goal is NOT to duplicate the existing + * pass/fail/skip reporting. (So the callback + * does not accept a status/errorcode argument.) + * + */ +typedef enum cl_trace_event { + CL_TRACE__SUITE_BEGIN, + CL_TRACE__SUITE_END, + CL_TRACE__TEST__BEGIN, + CL_TRACE__TEST__END, + CL_TRACE__TEST__RUN_BEGIN, + CL_TRACE__TEST__RUN_END, + CL_TRACE__TEST__LONGJMP, +} cl_trace_event; + +typedef void (cl_trace_cb)( + cl_trace_event ev, + const char *suite_name, + const char *test_name, + void *payload); + +/** + * Register a callback into CLAR to send global trace events. + * Pass NULL to disable. + */ +void cl_trace_register(cl_trace_cb *cb, void *payload); + + +#ifdef CLAR_FIXTURE_PATH +const char *cl_fixture(const char *fixture_name); +void cl_fixture_sandbox(const char *fixture_name); +void cl_fixture_cleanup(const char *fixture_name); +const char *cl_fixture_basename(const char *fixture_name); +#endif + +/** + * Assertion macros with explicit error message + */ +#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1) +#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1) +#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1) + +/** + * Check macros with explicit error message + */ +#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0) +#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0) +#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0) + +/** + * Assertion macros with no error message + */ +#define cl_must_pass(expr) cl_must_pass_(expr, NULL) +#define cl_must_fail(expr) cl_must_fail_(expr, NULL) +#define cl_assert(expr) cl_assert_(expr, NULL) + +/** + * Check macros with no error message + */ +#define cl_check_pass(expr) cl_check_pass_(expr, NULL) +#define cl_check_fail(expr) cl_check_fail_(expr, NULL) +#define cl_check(expr) cl_check_(expr, NULL) + +/** + * Forced failure/warning + */ +#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1) +#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0) + +#define cl_skip() clar__skip() + +/** + * Typed assertion macros + */ +#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) + +#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2)) +#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2)) + +#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len)) +#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len)) + +#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len)) +#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len)) + +#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) +#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) + +#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) + +#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) + +void clar__skip(void); + +void clar__fail( + const char *file, + const char *func, + size_t line, + const char *error, + const char *description, + int should_abort); + +void clar__assert( + int condition, + const char *file, + const char *func, + size_t line, + const char *error, + const char *description, + int should_abort); + +void clar__assert_equal( + const char *file, + const char *func, + size_t line, + const char *err, + int should_abort, + const char *fmt, + ...); + +#endif diff --git a/t/unit-tests/clar/clar/fixtures.h b/t/unit-tests/clar/clar/fixtures.h new file mode 100644 index 0000000000..6ec6423484 --- /dev/null +++ b/t/unit-tests/clar/clar/fixtures.h @@ -0,0 +1,50 @@ +#ifdef CLAR_FIXTURE_PATH +static const char * +fixture_path(const char *base, const char *fixture_name) +{ + static char _path[4096]; + size_t root_len; + + root_len = strlen(base); + strncpy(_path, base, sizeof(_path)); + + if (_path[root_len - 1] != '/') + _path[root_len++] = '/'; + + if (fixture_name[0] == '/') + fixture_name++; + + strncpy(_path + root_len, + fixture_name, + sizeof(_path) - root_len); + + return _path; +} + +const char *cl_fixture(const char *fixture_name) +{ + return fixture_path(CLAR_FIXTURE_PATH, fixture_name); +} + +void cl_fixture_sandbox(const char *fixture_name) +{ + fs_copy(cl_fixture(fixture_name), _clar_path); +} + +const char *cl_fixture_basename(const char *fixture_name) +{ + const char *p; + + for (p = fixture_name; *p; p++) { + if (p[0] == '/' && p[1] && p[1] != '/') + fixture_name = p+1; + } + + return fixture_name; +} + +void cl_fixture_cleanup(const char *fixture_name) +{ + fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name))); +} +#endif diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h new file mode 100644 index 0000000000..8b206179fc --- /dev/null +++ b/t/unit-tests/clar/clar/fs.h @@ -0,0 +1,524 @@ +/* + * By default, use a read/write loop to copy files on POSIX systems. + * On Linux, use sendfile by default as it's slightly faster. On + * macOS, we avoid fcopyfile by default because it's slightly slower. + */ +#undef USE_FCOPYFILE +#define USE_SENDFILE 1 + +#ifdef _WIN32 + +#ifdef CLAR_WIN32_LONGPATHS +# define CLAR_MAX_PATH 4096 +#else +# define CLAR_MAX_PATH MAX_PATH +#endif + +#define RM_RETRY_COUNT 5 +#define RM_RETRY_DELAY 10 + +#ifdef __MINGW32__ + +/* These security-enhanced functions are not available + * in MinGW, so just use the vanilla ones */ +#define wcscpy_s(a, b, c) wcscpy((a), (c)) +#define wcscat_s(a, b, c) wcscat((a), (c)) + +#endif /* __MINGW32__ */ + +static int +fs__dotordotdot(WCHAR *_tocheck) +{ + return _tocheck[0] == '.' && + (_tocheck[1] == '\0' || + (_tocheck[1] == '.' && _tocheck[2] == '\0')); +} + +static int +fs_rmdir_rmdir(WCHAR *_wpath) +{ + unsigned retries = 1; + + while (!RemoveDirectoryW(_wpath)) { + /* Only retry when we have retries remaining, and the + * error was ERROR_DIR_NOT_EMPTY. */ + if (retries++ > RM_RETRY_COUNT || + ERROR_DIR_NOT_EMPTY != GetLastError()) + return -1; + + /* Give whatever has a handle to a child item some time + * to release it before trying again */ + Sleep(RM_RETRY_DELAY * retries * retries); + } + + return 0; +} + +static void translate_path(WCHAR *path, size_t path_size) +{ + size_t path_len, i; + + if (wcsncmp(path, L"\\\\?\\", 4) == 0) + return; + + path_len = wcslen(path); + cl_assert(path_size > path_len + 4); + + for (i = path_len; i > 0; i--) { + WCHAR c = path[i - 1]; + + if (c == L'/') + path[i + 3] = L'\\'; + else + path[i + 3] = path[i - 1]; + } + + path[0] = L'\\'; + path[1] = L'\\'; + path[2] = L'?'; + path[3] = L'\\'; + path[path_len + 4] = L'\0'; +} + +static void +fs_rmdir_helper(WCHAR *_wsource) +{ + WCHAR buffer[CLAR_MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + size_t buffer_prefix_len; + + /* Set up the buffer and capture the length */ + wcscpy_s(buffer, CLAR_MAX_PATH, _wsource); + translate_path(buffer, CLAR_MAX_PATH); + wcscat_s(buffer, CLAR_MAX_PATH, L"\\"); + buffer_prefix_len = wcslen(buffer); + + /* FindFirstFile needs a wildcard to match multiple items */ + wcscat_s(buffer, CLAR_MAX_PATH, L"*"); + find_handle = FindFirstFileW(buffer, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buffer + buffer_prefix_len, CLAR_MAX_PATH - buffer_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_rmdir_helper(buffer); + else { + /* If set, the +R bit must be cleared before deleting */ + if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes) + cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(buffer)); + } + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); + + /* Now that the directory is empty, remove it */ + cl_assert(0 == fs_rmdir_rmdir(_wsource)); +} + +static int +fs_rm_wait(WCHAR *_wpath) +{ + unsigned retries = 1; + DWORD last_error; + + do { + if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath)) + last_error = GetLastError(); + else + last_error = ERROR_SUCCESS; + + /* Is the item gone? */ + if (ERROR_FILE_NOT_FOUND == last_error || + ERROR_PATH_NOT_FOUND == last_error) + return 0; + + Sleep(RM_RETRY_DELAY * retries * retries); + } + while (retries++ <= RM_RETRY_COUNT); + + return -1; +} + +static void +fs_rm(const char *_source) +{ + WCHAR wsource[CLAR_MAX_PATH]; + DWORD attrs; + + /* The input path is UTF-8. Convert it to wide characters + * for use with the Windows API */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, /* Indicates NULL termination */ + wsource, + CLAR_MAX_PATH)); + + translate_path(wsource, CLAR_MAX_PATH); + + /* Does the item exist? If not, we have no work to do */ + attrs = GetFileAttributesW(wsource); + + if (INVALID_FILE_ATTRIBUTES == attrs) + return; + + if (FILE_ATTRIBUTE_DIRECTORY & attrs) + fs_rmdir_helper(wsource); + else { + /* The item is a file. Strip the +R bit */ + if (FILE_ATTRIBUTE_READONLY & attrs) + cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(wsource)); + } + + /* Wait for the DeleteFile or RemoveDirectory call to complete */ + cl_assert(0 == fs_rm_wait(wsource)); +} + +static void +fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest) +{ + WCHAR buf_source[CLAR_MAX_PATH], buf_dest[CLAR_MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + size_t buf_source_prefix_len, buf_dest_prefix_len; + + wcscpy_s(buf_source, CLAR_MAX_PATH, _wsource); + wcscat_s(buf_source, CLAR_MAX_PATH, L"\\"); + translate_path(buf_source, CLAR_MAX_PATH); + buf_source_prefix_len = wcslen(buf_source); + + wcscpy_s(buf_dest, CLAR_MAX_PATH, _wdest); + wcscat_s(buf_dest, CLAR_MAX_PATH, L"\\"); + translate_path(buf_dest, CLAR_MAX_PATH); + buf_dest_prefix_len = wcslen(buf_dest); + + /* Get an enumerator for the items in the source. */ + wcscat_s(buf_source, CLAR_MAX_PATH, L"*"); + find_handle = FindFirstFileW(buf_source, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + /* Create the target directory. */ + cl_assert(CreateDirectoryW(_wdest, NULL)); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buf_source + buf_source_prefix_len, CLAR_MAX_PATH - buf_source_prefix_len, find_data.cFileName); + wcscpy_s(buf_dest + buf_dest_prefix_len, CLAR_MAX_PATH - buf_dest_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_copydir_helper(buf_source, buf_dest); + else + cl_assert(CopyFileW(buf_source, buf_dest, TRUE)); + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); +} + +static void +fs_copy(const char *_source, const char *_dest) +{ + WCHAR wsource[CLAR_MAX_PATH], wdest[CLAR_MAX_PATH]; + DWORD source_attrs, dest_attrs; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + + /* The input paths are UTF-8. Convert them to wide characters + * for use with the Windows API. */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, + wsource, + CLAR_MAX_PATH)); + + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _dest, + -1, + wdest, + CLAR_MAX_PATH)); + + translate_path(wsource, CLAR_MAX_PATH); + translate_path(wdest, CLAR_MAX_PATH); + + /* Check the source for existence */ + source_attrs = GetFileAttributesW(wsource); + cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs); + + /* Check the target for existence */ + dest_attrs = GetFileAttributesW(wdest); + + if (INVALID_FILE_ATTRIBUTES != dest_attrs) { + /* Target exists; append last path part of source to target. + * Use FindFirstFile to parse the path */ + find_handle = FindFirstFileW(wsource, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + wcscat_s(wdest, CLAR_MAX_PATH, L"\\"); + wcscat_s(wdest, CLAR_MAX_PATH, find_data.cFileName); + FindClose(find_handle); + + /* Check the new target for existence */ + cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest)); + } + + if (FILE_ATTRIBUTE_DIRECTORY & source_attrs) + fs_copydir_helper(wsource, wdest); + else + cl_assert(CopyFileW(wsource, wdest, TRUE)); +} + +void +cl_fs_cleanup(void) +{ +#ifdef CLAR_FIXTURE_PATH + fs_rm(fixture_path(_clar_path, "*")); +#else + ((void)fs_copy); /* unused */ +#endif +} + +#else + +#include <errno.h> +#include <string.h> +#include <limits.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#if defined(__linux__) +# include <sys/sendfile.h> +#endif + +#if defined(__APPLE__) +# include <copyfile.h> +#endif + +static void basename_r(const char **out, int *out_len, const char *in) +{ + size_t in_len = strlen(in), start_pos; + + for (in_len = strlen(in); in_len; in_len--) { + if (in[in_len - 1] != '/') + break; + } + + for (start_pos = in_len; start_pos; start_pos--) { + if (in[start_pos - 1] == '/') + break; + } + + cl_assert(in_len - start_pos < INT_MAX); + + if (in_len - start_pos > 0) { + *out = &in[start_pos]; + *out_len = (in_len - start_pos); + } else { + *out = "/"; + *out_len = 1; + } +} + +static char *joinpath(const char *dir, const char *base, int base_len) +{ + char *out; + int len; + + if (base_len == -1) { + size_t bl = strlen(base); + + cl_assert(bl < INT_MAX); + base_len = (int)bl; + } + + len = strlen(dir) + base_len + 2; + cl_assert(len > 0); + + cl_assert(out = malloc(len)); + cl_assert(snprintf(out, len, "%s/%.*s", dir, base_len, base) < len); + + return out; +} + +static void +fs_copydir_helper(const char *source, const char *dest, int dest_mode) +{ + DIR *source_dir; + struct dirent *d; + + mkdir(dest, dest_mode); + + cl_assert_(source_dir = opendir(source), "Could not open source dir"); + while ((d = (errno = 0, readdir(source_dir))) != NULL) { + char *child; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + child = joinpath(source, d->d_name, -1); + fs_copy(child, dest); + free(child); + } + + cl_assert_(errno == 0, "Failed to iterate source dir"); + + closedir(source_dir); +} + +static void +fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int dest_mode) +{ + int in, out; + + cl_must_pass((in = open(source, O_RDONLY))); + cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode))); + +#if USE_FCOPYFILE && defined(__APPLE__) + ((void)(source_len)); /* unused */ + cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA)); +#elif USE_SENDFILE && defined(__linux__) + { + ssize_t ret = 0; + + while (source_len && (ret = sendfile(out, in, NULL, source_len)) > 0) { + source_len -= (size_t)ret; + } + cl_assert(ret >= 0); + } +#else + { + char buf[131072]; + ssize_t ret; + + ((void)(source_len)); /* unused */ + + while ((ret = read(in, buf, sizeof(buf))) > 0) { + size_t len = (size_t)ret; + + while (len && (ret = write(out, buf, len)) > 0) { + cl_assert(ret <= (ssize_t)len); + len -= ret; + } + cl_assert(ret >= 0); + } + cl_assert(ret == 0); + } +#endif + + close(in); + close(out); +} + +static void +fs_copy(const char *source, const char *_dest) +{ + char *dbuf = NULL; + const char *dest = NULL; + struct stat source_st, dest_st; + + cl_must_pass_(lstat(source, &source_st), "Failed to stat copy source"); + + if (lstat(_dest, &dest_st) == 0) { + const char *base; + int base_len; + + /* Target exists and is directory; append basename */ + cl_assert(S_ISDIR(dest_st.st_mode)); + + basename_r(&base, &base_len, source); + cl_assert(base_len < INT_MAX); + + dbuf = joinpath(_dest, base, base_len); + dest = dbuf; + } else if (errno != ENOENT) { + cl_fail("Cannot copy; cannot stat destination"); + } else { + dest = _dest; + } + + if (S_ISDIR(source_st.st_mode)) { + fs_copydir_helper(source, dest, source_st.st_mode); + } else { + fs_copyfile_helper(source, source_st.st_size, dest, source_st.st_mode); + } + + free(dbuf); +} + +static void +fs_rmdir_helper(const char *path) +{ + DIR *dir; + struct dirent *d; + + cl_assert_(dir = opendir(path), "Could not open dir"); + while ((d = (errno = 0, readdir(dir))) != NULL) { + char *child; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + child = joinpath(path, d->d_name, -1); + fs_rm(child); + free(child); + } + + cl_assert_(errno == 0, "Failed to iterate source dir"); + closedir(dir); + + cl_must_pass_(rmdir(path), "Could not remove directory"); +} + +static void +fs_rm(const char *path) +{ + struct stat st; + + if (lstat(path, &st)) { + if (errno == ENOENT) + return; + + cl_fail("Cannot copy; cannot stat destination"); + } + + if (S_ISDIR(st.st_mode)) { + fs_rmdir_helper(path); + } else { + cl_must_pass(unlink(path)); + } +} + +void +cl_fs_cleanup(void) +{ + clar_unsandbox(); + clar_sandbox(); +} +#endif diff --git a/t/unit-tests/clar/clar/print.h b/t/unit-tests/clar/clar/print.h new file mode 100644 index 0000000000..69d0ee967e --- /dev/null +++ b/t/unit-tests/clar/clar/print.h @@ -0,0 +1,216 @@ +/* clap: clar protocol, the traditional clar output format */ + +static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names) +{ + (void)test_count; + printf("Loaded %d suites: %s\n", (int)suite_count, suite_names); + printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n"); +} + +static void clar_print_clap_shutdown(int test_count, int suite_count, int error_count) +{ + (void)test_count; + (void)suite_count; + (void)error_count; + + printf("\n\n"); + clar_report_all(); +} + +static void clar_print_clap_error(int num, const struct clar_report *report, const struct clar_error *error) +{ + printf(" %d) Failure:\n", num); + + printf("%s::%s [%s:%"PRIuMAX"]\n", + report->suite, + report->test, + error->file, + error->line_number); + + printf(" %s\n", error->error_msg); + + if (error->description != NULL) + printf(" %s\n", error->description); + + printf("\n"); + fflush(stdout); +} + +static void clar_print_clap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) +{ + (void)test_name; + (void)test_number; + + if (_clar.verbosity > 1) { + printf("%s::%s: ", suite_name, test_name); + + switch (status) { + case CL_TEST_OK: printf("ok\n"); break; + case CL_TEST_FAILURE: printf("fail\n"); break; + case CL_TEST_SKIP: printf("skipped"); break; + case CL_TEST_NOTRUN: printf("notrun"); break; + } + } else { + switch (status) { + case CL_TEST_OK: printf("."); break; + case CL_TEST_FAILURE: printf("F"); break; + case CL_TEST_SKIP: printf("S"); break; + case CL_TEST_NOTRUN: printf("N"); break; + } + + fflush(stdout); + } +} + +static void clar_print_clap_onsuite(const char *suite_name, int suite_index) +{ + if (_clar.verbosity == 1) + printf("\n%s", suite_name); + + (void)suite_index; +} + +static void clar_print_clap_onabort(const char *fmt, va_list arg) +{ + vfprintf(stderr, fmt, arg); +} + +/* tap: test anywhere protocol format */ + +static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names) +{ + (void)test_count; + (void)suite_count; + (void)suite_names; + printf("TAP version 13\n"); +} + +static void clar_print_tap_shutdown(int test_count, int suite_count, int error_count) +{ + (void)suite_count; + (void)error_count; + + printf("1..%d\n", test_count); +} + +static void clar_print_tap_error(int num, const struct clar_report *report, const struct clar_error *error) +{ + (void)num; + (void)report; + (void)error; +} + +static void print_escaped(const char *str) +{ + char *c; + + while ((c = strchr(str, '\'')) != NULL) { + printf("%.*s", (int)(c - str), str); + printf("''"); + str = c + 1; + } + + printf("%s", str); +} + +static void clar_print_tap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) +{ + const struct clar_error *error = _clar.last_report->errors; + + (void)test_name; + (void)test_number; + + switch(status) { + case CL_TEST_OK: + printf("ok %d - %s::%s\n", test_number, suite_name, test_name); + break; + case CL_TEST_FAILURE: + printf("not ok %d - %s::%s\n", test_number, suite_name, test_name); + + printf(" ---\n"); + printf(" reason: |\n"); + printf(" %s\n", error->error_msg); + + if (error->description) + printf(" %s\n", error->description); + + printf(" at:\n"); + printf(" file: '"); print_escaped(error->file); printf("'\n"); + printf(" line: %" PRIuMAX "\n", error->line_number); + printf(" function: '%s'\n", error->function); + printf(" ---\n"); + + break; + case CL_TEST_SKIP: + case CL_TEST_NOTRUN: + printf("ok %d - # SKIP %s::%s\n", test_number, suite_name, test_name); + break; + } + + fflush(stdout); +} + +static void clar_print_tap_onsuite(const char *suite_name, int suite_index) +{ + printf("# start of suite %d: %s\n", suite_index, suite_name); +} + +static void clar_print_tap_onabort(const char *fmt, va_list arg) +{ + printf("Bail out! "); + vprintf(fmt, arg); + fflush(stdout); +} + +/* indirection between protocol output selection */ + +#define PRINT(FN, ...) do { \ + switch (_clar.output_format) { \ + case CL_OUTPUT_CLAP: \ + clar_print_clap_##FN (__VA_ARGS__); \ + break; \ + case CL_OUTPUT_TAP: \ + clar_print_tap_##FN (__VA_ARGS__); \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +static void clar_print_init(int test_count, int suite_count, const char *suite_names) +{ + PRINT(init, test_count, suite_count, suite_names); +} + +static void clar_print_shutdown(int test_count, int suite_count, int error_count) +{ + PRINT(shutdown, test_count, suite_count, error_count); +} + +static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error) +{ + PRINT(error, num, report, error); +} + +static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status) +{ + PRINT(ontest, suite_name, test_name, test_number, status); +} + +static void clar_print_onsuite(const char *suite_name, int suite_index) +{ + PRINT(onsuite, suite_name, suite_index); +} + +static void clar_print_onabortv(const char *msg, va_list argp) +{ + PRINT(onabort, msg, argp); +} + +static void clar_print_onabort(const char *msg, ...) +{ + va_list argp; + va_start(argp, msg); + clar_print_onabortv(msg, argp); + va_end(argp); +} diff --git a/t/unit-tests/clar/clar/sandbox.h b/t/unit-tests/clar/clar/sandbox.h new file mode 100644 index 0000000000..bc960f50e0 --- /dev/null +++ b/t/unit-tests/clar/clar/sandbox.h @@ -0,0 +1,158 @@ +#ifdef __APPLE__ +#include <sys/syslimits.h> +#endif + +static char _clar_path[4096 + 1]; + +static int +is_valid_tmp_path(const char *path) +{ + STAT_T st; + + if (stat(path, &st) != 0) + return 0; + + if (!S_ISDIR(st.st_mode)) + return 0; + + return (access(path, W_OK) == 0); +} + +static int +find_tmp_path(char *buffer, size_t length) +{ +#ifndef _WIN32 + static const size_t var_count = 5; + static const char *env_vars[] = { + "CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE" + }; + + size_t i; + + for (i = 0; i < var_count; ++i) { + const char *env = getenv(env_vars[i]); + if (!env) + continue; + + if (is_valid_tmp_path(env)) { +#ifdef __APPLE__ + if (length >= PATH_MAX && realpath(env, buffer) != NULL) + return 0; +#endif + strncpy(buffer, env, length - 1); + buffer[length - 1] = '\0'; + return 0; + } + } + + /* If the environment doesn't say anything, try to use /tmp */ + if (is_valid_tmp_path("/tmp")) { +#ifdef __APPLE__ + if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL) + return 0; +#endif + strncpy(buffer, "/tmp", length - 1); + buffer[length - 1] = '\0'; + return 0; + } + +#else + DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); + if (env_len > 0 && env_len < (DWORD)length) + return 0; + + if (GetTempPath((DWORD)length, buffer)) + return 0; +#endif + + /* This system doesn't like us, try to use the current directory */ + if (is_valid_tmp_path(".")) { + strncpy(buffer, ".", length - 1); + buffer[length - 1] = '\0'; + return 0; + } + + return -1; +} + +static void clar_unsandbox(void) +{ + if (_clar_path[0] == '\0') + return; + + cl_must_pass(chdir("..")); + + fs_rm(_clar_path); +} + +static int build_sandbox_path(void) +{ +#ifdef CLAR_TMPDIR + const char path_tail[] = CLAR_TMPDIR "_XXXXXX"; +#else + const char path_tail[] = "clar_tmp_XXXXXX"; +#endif + + size_t len; + + if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0) + return -1; + + len = strlen(_clar_path); + +#ifdef _WIN32 + { /* normalize path to POSIX forward slashes */ + size_t i; + for (i = 0; i < len; ++i) { + if (_clar_path[i] == '\\') + _clar_path[i] = '/'; + } + } +#endif + + if (_clar_path[len - 1] != '/') { + _clar_path[len++] = '/'; + } + + strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len); + +#if defined(__MINGW32__) + if (_mktemp(_clar_path) == NULL) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#elif defined(_WIN32) + if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#elif defined(__sun) || defined(__TANDEM) + if (mktemp(_clar_path) == NULL) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#else + if (mkdtemp(_clar_path) == NULL) + return -1; +#endif + + return 0; +} + +static void clar_sandbox(void) +{ + if (_clar_path[0] == '\0' && build_sandbox_path() < 0) + clar_abort("Failed to build sandbox path.\n"); + + if (chdir(_clar_path) != 0) + clar_abort("Failed to change into sandbox directory '%s': %s.\n", + _clar_path, strerror(errno)); +} + +const char *clar_sandbox_path(void) +{ + return _clar_path; +} diff --git a/t/unit-tests/clar/clar/summary.h b/t/unit-tests/clar/clar/summary.h new file mode 100644 index 0000000000..0d0b646fe7 --- /dev/null +++ b/t/unit-tests/clar/clar/summary.h @@ -0,0 +1,139 @@ + +#include <stdio.h> +#include <time.h> + +static int clar_summary_close_tag( + struct clar_summary *summary, const char *tag, int indent) +{ + const char *indt; + + if (indent == 0) indt = ""; + else if (indent == 1) indt = "\t"; + else indt = "\t\t"; + + return fprintf(summary->fp, "%s</%s>\n", indt, tag); +} + +static int clar_summary_testsuites(struct clar_summary *summary) +{ + return fprintf(summary->fp, "<testsuites>\n"); +} + +static int clar_summary_testsuite(struct clar_summary *summary, + int idn, const char *name, time_t timestamp, + int test_count, int fail_count, int error_count) +{ + struct tm *tm = localtime(×tamp); + char iso_dt[20]; + + if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0) + return -1; + + return fprintf(summary->fp, "\t<testsuite" + " id=\"%d\"" + " name=\"%s\"" + " hostname=\"localhost\"" + " timestamp=\"%s\"" + " tests=\"%d\"" + " failures=\"%d\"" + " errors=\"%d\">\n", + idn, name, iso_dt, test_count, fail_count, error_count); +} + +static int clar_summary_testcase(struct clar_summary *summary, + const char *name, const char *classname, double elapsed) +{ + return fprintf(summary->fp, + "\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n", + name, classname, elapsed); +} + +static int clar_summary_failure(struct clar_summary *summary, + const char *type, const char *message, const char *desc) +{ + return fprintf(summary->fp, + "\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n", + type, message, desc); +} + +static int clar_summary_skipped(struct clar_summary *summary) +{ + return fprintf(summary->fp, "\t\t\t<skipped />\n"); +} + +struct clar_summary *clar_summary_init(const char *filename) +{ + struct clar_summary *summary; + FILE *fp; + + if ((fp = fopen(filename, "w")) == NULL) + clar_abort("Failed to open the summary file '%s': %s.\n", + filename, strerror(errno)); + + if ((summary = malloc(sizeof(struct clar_summary))) == NULL) + clar_abort("Failed to allocate summary.\n"); + + summary->filename = filename; + summary->fp = fp; + + return summary; +} + +int clar_summary_shutdown(struct clar_summary *summary) +{ + struct clar_report *report; + const char *last_suite = NULL; + + if (clar_summary_testsuites(summary) < 0) + goto on_error; + + report = _clar.reports; + while (report != NULL) { + struct clar_error *error = report->errors; + + if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) { + if (clar_summary_testsuite(summary, 0, report->suite, + report->start, _clar.tests_ran, _clar.total_errors, 0) < 0) + goto on_error; + } + + last_suite = report->suite; + + clar_summary_testcase(summary, report->test, report->suite, report->elapsed); + + while (error != NULL) { + if (clar_summary_failure(summary, "assert", + error->error_msg, error->description) < 0) + goto on_error; + + error = error->next; + } + + if (report->status == CL_TEST_SKIP) + clar_summary_skipped(summary); + + if (clar_summary_close_tag(summary, "testcase", 2) < 0) + goto on_error; + + report = report->next; + + if (!report || strcmp(last_suite, report->suite) != 0) { + if (clar_summary_close_tag(summary, "testsuite", 1) < 0) + goto on_error; + } + } + + if (clar_summary_close_tag(summary, "testsuites", 0) < 0 || + fclose(summary->fp) != 0) + goto on_error; + + printf("written summary file to %s\n", summary->filename); + + free(summary); + return 0; + +on_error: + fclose(summary->fp); + free(summary); + return -1; +} diff --git a/t/unit-tests/clar/generate.py b/t/unit-tests/clar/generate.py new file mode 100755 index 0000000000..80996ac3e7 --- /dev/null +++ b/t/unit-tests/clar/generate.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python +# +# Copyright (c) Vicent Marti. All rights reserved. +# +# This file is part of clar, distributed under the ISC license. +# For full terms see the included COPYING file. +# + +from __future__ import with_statement +from string import Template +import re, fnmatch, os, sys, codecs, pickle + +class Module(object): + class Template(object): + def __init__(self, module): + self.module = module + + def _render_callback(self, cb): + if not cb: + return ' { NULL, NULL }' + return ' { "%s", &%s }' % (cb['short_name'], cb['symbol']) + + class DeclarationTemplate(Template): + def render(self): + out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + "\n" + + for initializer in self.module.initializers: + out += "extern %s;\n" % initializer['declaration'] + + if self.module.cleanup: + out += "extern %s;\n" % self.module.cleanup['declaration'] + + return out + + class CallbacksTemplate(Template): + def render(self): + out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name + out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks) + out += "\n};\n" + return out + + class InfoTemplate(Template): + def render(self): + templates = [] + + initializers = self.module.initializers + if len(initializers) == 0: + initializers = [ None ] + + for initializer in initializers: + name = self.module.clean_name() + if initializer and initializer['short_name'].startswith('initialize_'): + variant = initializer['short_name'][len('initialize_'):] + name += " (%s)" % variant.replace('_', ' ') + + template = Template( + r""" + { + "${clean_name}", + ${initialize}, + ${cleanup}, + ${cb_ptr}, ${cb_count}, ${enabled} + }""" + ).substitute( + clean_name = name, + initialize = self._render_callback(initializer), + cleanup = self._render_callback(self.module.cleanup), + cb_ptr = "_clar_cb_%s" % self.module.name, + cb_count = len(self.module.callbacks), + enabled = int(self.module.enabled) + ) + templates.append(template) + + return ','.join(templates) + + def __init__(self, name): + self.name = name + + self.mtime = None + self.enabled = True + self.modified = False + + def clean_name(self): + return self.name.replace("_", "::") + + def _skip_comments(self, text): + SKIP_COMMENTS_REGEX = re.compile( + r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', + re.DOTALL | re.MULTILINE) + + def _replacer(match): + s = match.group(0) + return "" if s.startswith('/') else s + + return re.sub(SKIP_COMMENTS_REGEX, _replacer, text) + + def parse(self, contents): + TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\s*\(\s*void\s*\))\s*\{" + + contents = self._skip_comments(contents) + regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE) + + self.callbacks = [] + self.initializers = [] + self.cleanup = None + + for (declaration, symbol, short_name) in regex.findall(contents): + data = { + "short_name" : short_name, + "declaration" : declaration, + "symbol" : symbol + } + + if short_name.startswith('initialize'): + self.initializers.append(data) + elif short_name == 'cleanup': + self.cleanup = data + else: + self.callbacks.append(data) + + return self.callbacks != [] + + def refresh(self, path): + self.modified = False + + try: + st = os.stat(path) + + # Not modified + if st.st_mtime == self.mtime: + return True + + self.modified = True + self.mtime = st.st_mtime + + with codecs.open(path, encoding='utf-8') as fp: + raw_content = fp.read() + + except IOError: + return False + + return self.parse(raw_content) + +class TestSuite(object): + + def __init__(self, path, output): + self.path = path + self.output = output + + def should_generate(self, path): + if not os.path.isfile(path): + return True + + if any(module.modified for module in self.modules.values()): + return True + + return False + + def find_modules(self): + modules = [] + for root, _, files in os.walk(self.path): + module_root = root[len(self.path):] + module_root = [c for c in module_root.split(os.sep) if c] + + tests_in_module = fnmatch.filter(files, "*.c") + + for test_file in tests_in_module: + full_path = os.path.join(root, test_file) + module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_") + + modules.append((full_path, module_name)) + + return modules + + def load_cache(self): + path = os.path.join(self.output, '.clarcache') + cache = {} + + try: + fp = open(path, 'rb') + cache = pickle.load(fp) + fp.close() + except (IOError, ValueError): + pass + + return cache + + def save_cache(self): + path = os.path.join(self.output, '.clarcache') + with open(path, 'wb') as cache: + pickle.dump(self.modules, cache) + + def load(self, force = False): + module_data = self.find_modules() + self.modules = {} if force else self.load_cache() + + for path, name in module_data: + if name not in self.modules: + self.modules[name] = Module(name) + + if not self.modules[name].refresh(path): + del self.modules[name] + + def disable(self, excluded): + for exclude in excluded: + for module in self.modules.values(): + name = module.clean_name() + if name.startswith(exclude): + module.enabled = False + module.modified = True + + def suite_count(self): + return sum(max(1, len(m.initializers)) for m in self.modules.values()) + + def callback_count(self): + return sum(len(module.callbacks) for module in self.modules.values()) + + def write(self): + output = os.path.join(self.output, 'clar.suite') + + if not self.should_generate(output): + return False + + with open(output, 'w') as data: + modules = sorted(self.modules.values(), key=lambda module: module.name) + + for module in modules: + t = Module.DeclarationTemplate(module) + data.write(t.render()) + + for module in modules: + t = Module.CallbacksTemplate(module) + data.write(t.render()) + + suites = "static struct clar_suite _clar_suites[] = {" + ','.join( + Module.InfoTemplate(module).render() for module in modules + ) + "\n};\n" + + data.write(suites) + + data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count()) + data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count()) + + self.save_cache() + return True + +if __name__ == '__main__': + from optparse import OptionParser + + parser = OptionParser() + parser.add_option('-f', '--force', action="store_true", dest='force', default=False) + parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[]) + parser.add_option('-o', '--output', dest='output') + + options, args = parser.parse_args() + if len(args) > 1: + print("More than one path given") + sys.exit(1) + + path = args.pop() if args else '.' + output = options.output or path + suite = TestSuite(path, output) + suite.load(options.force) + suite.disable(options.excluded) + if suite.write(): + print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count())) diff --git a/t/unit-tests/clar/test/CMakeLists.txt b/t/unit-tests/clar/test/CMakeLists.txt new file mode 100644 index 0000000000..7f2c1dc17a --- /dev/null +++ b/t/unit-tests/clar/test/CMakeLists.txt @@ -0,0 +1,39 @@ +find_package(Python COMPONENTS Interpreter REQUIRED) + +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite" + COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}" + DEPENDS main.c sample.c clar_test.h + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +) + +add_executable(clar_test) +set_target_properties(clar_test PROPERTIES + C_STANDARD 90 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF +) + +# MSVC generates all kinds of warnings. We may want to fix these in the future +# and then unconditionally treat warnings as errors. +if(NOT MSVC) + set_target_properties(clar_test PROPERTIES + COMPILE_WARNING_AS_ERROR ON + ) +endif() + +target_sources(clar_test PRIVATE + main.c + sample.c + "${CMAKE_CURRENT_BINARY_DIR}/clar.suite" +) +target_compile_definitions(clar_test PRIVATE + CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/" +) +target_compile_options(clar_test PRIVATE + $<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall> +) +target_include_directories(clar_test PRIVATE + "${CMAKE_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}" +) +target_link_libraries(clar_test clar) diff --git a/t/unit-tests/clar/test/clar_test.h b/t/unit-tests/clar/test/clar_test.h new file mode 100644 index 0000000000..0fcaa639aa --- /dev/null +++ b/t/unit-tests/clar/test/clar_test.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ +#ifndef __CLAR_TEST__ +#define __CLAR_TEST__ + +/* Import the standard clar helper functions */ +#include "clar.h" + +/* Your custom shared includes / defines here */ +extern int global_test_counter; + +#endif diff --git a/t/unit-tests/clar/test/main.c b/t/unit-tests/clar/test/main.c new file mode 100644 index 0000000000..59e56ad255 --- /dev/null +++ b/t/unit-tests/clar/test/main.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ + +#include "clar_test.h" + +/* + * Sample main() for clar tests. + * + * You should write your own main routine for clar tests that does specific + * setup and teardown as necessary for your application. The only required + * line is the call to `clar_test(argc, argv)`, which will execute the test + * suite. If you want to check the return value of the test application, + * your main() should return the same value returned by clar_test(). + */ + +int global_test_counter = 0; + +#ifdef _WIN32 +int __cdecl main(int argc, char *argv[]) +#else +int main(int argc, char *argv[]) +#endif +{ + int ret; + + /* Your custom initialization here */ + global_test_counter = 0; + + /* Run the test suite */ + ret = clar_test(argc, argv); + + /* Your custom cleanup here */ + cl_assert_equal_i(8, global_test_counter); + + return ret; +} diff --git a/t/unit-tests/clar/test/main.c.sample b/t/unit-tests/clar/test/main.c.sample new file mode 100644 index 0000000000..a4d91b72fa --- /dev/null +++ b/t/unit-tests/clar/test/main.c.sample @@ -0,0 +1,27 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ + +#include "clar_test.h" + +/* + * Minimal main() for clar tests. + * + * Modify this with any application specific setup or teardown that you need. + * The only required line is the call to `clar_test(argc, argv)`, which will + * execute the test suite. If you want to check the return value of the test + * application, main() should return the same value returned by clar_test(). + */ + +#ifdef _WIN32 +int __cdecl main(int argc, char *argv[]) +#else +int main(int argc, char *argv[]) +#endif +{ + /* Run the test suite */ + return clar_test(argc, argv); +} diff --git a/t/unit-tests/clar/test/resources/test/file b/t/unit-tests/clar/test/resources/test/file new file mode 100644 index 0000000000..220f4aa98a --- /dev/null +++ b/t/unit-tests/clar/test/resources/test/file @@ -0,0 +1 @@ +File diff --git a/t/unit-tests/clar/test/sample.c b/t/unit-tests/clar/test/sample.c new file mode 100644 index 0000000000..faa1209262 --- /dev/null +++ b/t/unit-tests/clar/test/sample.c @@ -0,0 +1,84 @@ +#include "clar_test.h" +#include <sys/stat.h> + +static int file_size(const char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) + return (int)st.st_size; + return -1; +} + +void test_sample__initialize(void) +{ + global_test_counter++; +} + +void test_sample__cleanup(void) +{ + cl_fixture_cleanup("test"); + + cl_assert(file_size("test/file") == -1); +} + +void test_sample__1(void) +{ + cl_assert(1); + cl_must_pass(0); /* 0 == success */ + cl_must_fail(-1); /* <0 == failure */ + cl_must_pass(-1); /* demonstrate a failing call */ +} + +void test_sample__2(void) +{ + cl_fixture_sandbox("test"); + + cl_assert(file_size("test/nonexistent") == -1); + cl_assert(file_size("test/file") > 0); + cl_assert(100 == 101); +} + +void test_sample__strings(void) +{ + const char *actual = "expected"; + cl_assert_equal_s("expected", actual); + cl_assert_equal_s_("expected", actual, "second try with annotation"); + cl_assert_equal_s_("mismatched", actual, "this one fails"); +} + +void test_sample__strings_with_length(void) +{ + const char *actual = "expected"; + cl_assert_equal_strn("expected_", actual, 8); + cl_assert_equal_strn("exactly", actual, 2); + cl_assert_equal_strn_("expected_", actual, 8, "with annotation"); + cl_assert_equal_strn_("exactly", actual, 3, "this one fails"); +} + +void test_sample__int(void) +{ + int value = 100; + cl_assert_equal_i(100, value); + cl_assert_equal_i_(101, value, "extra note on failing test"); +} + +void test_sample__int_fmt(void) +{ + int value = 100; + cl_assert_equal_i_fmt(022, value, "%04o"); +} + +void test_sample__bool(void) +{ + int value = 100; + cl_assert_equal_b(1, value); /* test equality as booleans */ + cl_assert_equal_b(0, value); +} + +void test_sample__ptr(void) +{ + const char *actual = "expected"; + cl_assert_equal_p(actual, actual); /* pointers to same object */ + cl_assert_equal_p(&actual, actual); +} diff --git a/t/unit-tests/t-ctype.c b/t/unit-tests/ctype.c index d6ac1fe678..32e65867cd 100644 --- a/t/unit-tests/t-ctype.c +++ b/t/unit-tests/ctype.c @@ -1,18 +1,16 @@ -#include "test-lib.h" +#include "unit-test.h" #define TEST_CHAR_CLASS(class, string) do { \ size_t len = ARRAY_SIZE(string) - 1 + \ BUILD_ASSERT_OR_ZERO(ARRAY_SIZE(string) > 0) + \ BUILD_ASSERT_OR_ZERO(sizeof(string[0]) == sizeof(char)); \ - int skip = test__run_begin(); \ - if (!skip) { \ - for (int i = 0; i < 256; i++) { \ - if (!check_int(class(i), ==, !!memchr(string, i, len)))\ - test_msg(" i: 0x%02x", i); \ - } \ - check(!class(EOF)); \ + for (int i = 0; i < 256; i++) { \ + int actual = class(i), expect = !!memchr(string, i, len); \ + if (actual != expect) \ + cl_failf("0x%02x is classified incorrectly: expected %d, got %d", \ + i, expect, actual); \ } \ - test__run_end(!skip, TEST_LOCATION(), #class " works"); \ + cl_assert(!class(EOF)); \ } while (0) #define DIGIT "0123456789" @@ -33,21 +31,72 @@ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \ "\x7f" -int cmd_main(int argc, const char **argv) { +void test_ctype__isspace(void) +{ TEST_CHAR_CLASS(isspace, " \n\r\t"); +} + +void test_ctype__isdigit(void) +{ TEST_CHAR_CLASS(isdigit, DIGIT); +} + +void test_ctype__isalpha(void) +{ TEST_CHAR_CLASS(isalpha, LOWER UPPER); +} + +void test_ctype__isalnum(void) +{ TEST_CHAR_CLASS(isalnum, LOWER UPPER DIGIT); +} + +void test_ctype__is_glob_special(void) +{ TEST_CHAR_CLASS(is_glob_special, "*?[\\"); +} + +void test_ctype__is_regex_special(void) +{ TEST_CHAR_CLASS(is_regex_special, "$()*+.?[\\^{|"); +} + +void test_ctype__is_pathspec_magic(void) +{ TEST_CHAR_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~"); +} + +void test_ctype__isascii(void) +{ TEST_CHAR_CLASS(isascii, ASCII); +} + +void test_ctype__islower(void) +{ TEST_CHAR_CLASS(islower, LOWER); +} + +void test_ctype__isupper(void) +{ TEST_CHAR_CLASS(isupper, UPPER); +} + +void test_ctype__iscntrl(void) +{ TEST_CHAR_CLASS(iscntrl, CNTRL); +} + +void test_ctype__ispunct(void) +{ TEST_CHAR_CLASS(ispunct, PUNCT); +} + +void test_ctype__isxdigit(void) +{ TEST_CHAR_CLASS(isxdigit, DIGIT "abcdefABCDEF"); - TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " "); +} - return test_done(); +void test_ctype__isprint(void) +{ + TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " "); } diff --git a/t/unit-tests/generate-clar-decls.sh b/t/unit-tests/generate-clar-decls.sh new file mode 100755 index 0000000000..688e0885f4 --- /dev/null +++ b/t/unit-tests/generate-clar-decls.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +if test $# -lt 2 +then + echo "USAGE: $0 <OUTPUT> <SUITE>..." 2>&1 + exit 1 +fi + +OUTPUT="$1" +shift + +for suite in "$@" +do + sed -ne "s/^\(void test_$(basename "${suite%.c}")__[a-zA-Z_0-9][a-zA-Z_0-9]*(void)\)$/extern \1;/p" "$suite" || + exit 1 +done >"$OUTPUT" diff --git a/t/unit-tests/generate-clar-suites.sh b/t/unit-tests/generate-clar-suites.sh new file mode 100755 index 0000000000..d5c712221e --- /dev/null +++ b/t/unit-tests/generate-clar-suites.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +if test $# -lt 2 +then + echo "USAGE: $0 <CLAR_DECLS_H> <OUTPUT>" 2>&1 + exit 1 +fi + +CLAR_DECLS_H="$1" +OUTPUT="$2" + +awk ' + function add_suite(suite, initialize, cleanup, count) { + if (!suite) return + suite_count++ + callback_count += count + suites = suites " {\n" + suites = suites " \"" suite "\",\n" + suites = suites " " initialize ",\n" + suites = suites " " cleanup ",\n" + suites = suites " _clar_cb_" suite ", " count ", 1\n" + suites = suites " },\n" + } + + BEGIN { + suites = "static struct clar_suite _clar_suites[] = {\n" + } + + { + print + name = $3; sub(/\(.*$/, "", name) + suite = name; sub(/^test_/, "", suite); sub(/__.*$/, "", suite) + short_name = name; sub(/^.*__/, "", short_name) + cb = "{ \"" short_name "\", &" name " }" + if (suite != prev_suite) { + add_suite(prev_suite, initialize, cleanup, count) + if (callbacks) callbacks = callbacks "};\n" + callbacks = callbacks "static const struct clar_func _clar_cb_" suite "[] = {\n" + initialize = "{ NULL, NULL }" + cleanup = "{ NULL, NULL }" + count = 0 + prev_suite = suite + } + if (short_name == "initialize") { + initialize = cb + } else if (short_name == "cleanup") { + cleanup = cb + } else { + callbacks = callbacks " " cb ",\n" + count++ + } + } + + END { + add_suite(suite, initialize, cleanup, count) + suites = suites "};" + if (callbacks) callbacks = callbacks "};" + print callbacks + print suites + print "static const size_t _clar_suite_count = " suite_count ";" + print "static const size_t _clar_callback_count = " callback_count ";" + } +' "$CLAR_DECLS_H" >"$OUTPUT" diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c index 37105f0a8f..8f0ccac532 100644 --- a/t/unit-tests/lib-oid.c +++ b/t/unit-tests/lib-oid.c @@ -3,7 +3,7 @@ #include "strbuf.h" #include "hex.h" -static int init_hash_algo(void) +int init_hash_algo(void) { static int algo = -1; diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h index 8d2acca768..4e77c04bd2 100644 --- a/t/unit-tests/lib-oid.h +++ b/t/unit-tests/lib-oid.h @@ -13,5 +13,13 @@ * environment variable. */ int get_oid_arbitrary_hex(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 + * GIT_TEST_DEFAULT_HASH's value is valid or not. + */ +int init_hash_algo(void); #endif /* LIB_OID_H */ diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c new file mode 100644 index 0000000000..d795dfb7c9 --- /dev/null +++ b/t/unit-tests/lib-reftable.c @@ -0,0 +1,96 @@ +#include "lib-reftable.h" +#include "test-lib.h" +#include "reftable/constants.h" +#include "reftable/writer.h" +#include "strbuf.h" + +void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) +{ + memset(p, (uint8_t)i, hash_size(id)); +} + +static ssize_t strbuf_writer_write(void *b, const void *data, size_t sz) +{ + strbuf_add(b, data, sz); + return sz; +} + +static int strbuf_writer_flush(void *arg UNUSED) +{ + return 0; +} + +struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, + struct reftable_write_options *opts) +{ + struct reftable_writer *writer; + int ret = reftable_writer_new(&writer, &strbuf_writer_write, &strbuf_writer_flush, + buf, opts); + check(!ret); + return writer; +} + +void t_reftable_write_to_buf(struct reftable_buf *buf, + struct reftable_ref_record *refs, + size_t nrefs, + struct reftable_log_record *logs, + size_t nlogs, + struct reftable_write_options *_opts) +{ + struct reftable_write_options opts = { 0 }; + const struct reftable_stats *stats; + struct reftable_writer *writer; + uint64_t min = 0xffffffff; + uint64_t max = 0; + int ret; + + if (_opts) + opts = *_opts; + + for (size_t i = 0; i < nrefs; i++) { + uint64_t ui = refs[i].update_index; + if (ui > max) + max = ui; + if (ui < min) + min = ui; + } + for (size_t i = 0; i < nlogs; i++) { + uint64_t ui = logs[i].update_index; + if (ui > max) + max = ui; + if (ui < min) + min = ui; + } + + writer = t_reftable_strbuf_writer(buf, &opts); + reftable_writer_set_limits(writer, min, max); + + if (nrefs) { + ret = reftable_writer_add_refs(writer, refs, nrefs); + check_int(ret, ==, 0); + } + + if (nlogs) { + ret = reftable_writer_add_logs(writer, logs, nlogs); + check_int(ret, ==, 0); + } + + ret = reftable_writer_close(writer); + check_int(ret, ==, 0); + + stats = reftable_writer_stats(writer); + for (size_t i = 0; i < stats->ref_stats.blocks; i++) { + size_t off = i * (opts.block_size ? opts.block_size + : DEFAULT_BLOCK_SIZE); + if (!off) + off = header_size(opts.hash_id == REFTABLE_HASH_SHA256 ? 2 : 1); + check_char(buf->buf[off], ==, 'r'); + } + + if (nrefs) + check_int(stats->ref_stats.blocks, >, 0); + if (nlogs) + check_int(stats->log_stats.blocks, >, 0); + + reftable_writer_free(writer); +} diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h new file mode 100644 index 0000000000..e4c360fa7e --- /dev/null +++ b/t/unit-tests/lib-reftable.h @@ -0,0 +1,21 @@ +#ifndef LIB_REFTABLE_H +#define LIB_REFTABLE_H + +#include "git-compat-util.h" +#include "reftable/reftable-writer.h" + +struct reftable_buf; + +void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); + +struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, + struct reftable_write_options *opts); + +void t_reftable_write_to_buf(struct reftable_buf *buf, + struct reftable_ref_record *refs, + size_t nrecords, + struct reftable_log_record *logs, + size_t nlogs, + struct reftable_write_options *opts); + +#endif diff --git a/t/unit-tests/strvec.c b/t/unit-tests/strvec.c new file mode 100644 index 0000000000..e66b7bbfae --- /dev/null +++ b/t/unit-tests/strvec.c @@ -0,0 +1,316 @@ +#include "unit-test.h" +#include "strbuf.h" +#include "strvec.h" + +#define check_strvec(vec, ...) \ + do { \ + const char *expect[] = { __VA_ARGS__ }; \ + size_t expect_len = ARRAY_SIZE(expect); \ + cl_assert(expect_len > 0); \ + cl_assert_equal_p(expect[expect_len - 1], NULL); \ + cl_assert_equal_i((vec)->nr, expect_len - 1); \ + cl_assert((vec)->nr <= (vec)->alloc); \ + for (size_t i = 0; i < expect_len; i++) \ + cl_assert_equal_s((vec)->v[i], expect[i]); \ + } while (0) + +void test_strvec__init(void) +{ + struct strvec vec = STRVEC_INIT; + + cl_assert_equal_p(vec.v, empty_strvec); + cl_assert_equal_i(vec.nr, 0); + cl_assert_equal_i(vec.alloc, 0); +} + +void test_strvec__dynamic_init(void) +{ + struct strvec vec; + + strvec_init(&vec); + cl_assert_equal_p(vec.v, empty_strvec); + cl_assert_equal_i(vec.nr, 0); + cl_assert_equal_i(vec.alloc, 0); +} + +void test_strvec__clear(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_push(&vec, "foo"); + strvec_clear(&vec); + cl_assert_equal_p(vec.v, empty_strvec); + cl_assert_equal_i(vec.nr, 0); + cl_assert_equal_i(vec.alloc, 0); +} + +void test_strvec__push(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_push(&vec, "foo"); + check_strvec(&vec, "foo", NULL); + + strvec_push(&vec, "bar"); + check_strvec(&vec, "foo", "bar", NULL); + + strvec_clear(&vec); +} + +void test_strvec__pushf(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushf(&vec, "foo: %d", 1); + check_strvec(&vec, "foo: 1", NULL); + strvec_clear(&vec); +} + +void test_strvec__pushl(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + check_strvec(&vec, "foo", "bar", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__pushv(void) +{ + const char *strings[] = { + "foo", "bar", "baz", NULL, + }; + struct strvec vec = STRVEC_INIT; + + strvec_pushv(&vec, strings); + check_strvec(&vec, "foo", "bar", "baz", NULL); + + strvec_clear(&vec); +} + +void test_strvec__splice_just_initialized_strvec(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "foo" }; + + strvec_splice(&vec, 0, 0, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "foo", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_with_same_size_replacement(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "1" }; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_splice(&vec, 1, 1, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "foo", "1", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_with_smaller_replacement(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "1" }; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_splice(&vec, 1, 2, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "foo", "1", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_with_bigger_replacement(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "1", "2", "3" }; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_splice(&vec, 0, 2, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "1", "2", "3", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_with_empty_replacement(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_splice(&vec, 0, 2, NULL, 0); + check_strvec(&vec, "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_with_empty_original(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "1", "2" }; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_splice(&vec, 1, 0, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "foo", "1", "2", "bar", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__splice_at_tail(void) +{ + struct strvec vec = STRVEC_INIT; + const char *replacement[] = { "1", "2" }; + + strvec_pushl(&vec, "foo", "bar", NULL); + strvec_splice(&vec, 2, 0, replacement, ARRAY_SIZE(replacement)); + check_strvec(&vec, "foo", "bar", "1", "2", NULL); + strvec_clear(&vec); +} + +void test_strvec__replace_at_head(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_replace(&vec, 0, "replaced"); + check_strvec(&vec, "replaced", "bar", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__replace_at_tail(void) +{ + struct strvec vec = STRVEC_INIT; + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_replace(&vec, 2, "replaced"); + check_strvec(&vec, "foo", "bar", "replaced", NULL); + strvec_clear(&vec); +} + +void test_strvec__replace_in_between(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_replace(&vec, 1, "replaced"); + check_strvec(&vec, "foo", "replaced", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__replace_with_substring(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", NULL); + strvec_replace(&vec, 0, vec.v[0] + 1); + check_strvec(&vec, "oo", NULL); + strvec_clear(&vec); +} + +void test_strvec__remove_at_head(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_remove(&vec, 0); + check_strvec(&vec, "bar", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__remove_at_tail(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_remove(&vec, 2); + check_strvec(&vec, "foo", "bar", NULL); + strvec_clear(&vec); +} + +void test_strvec__remove_in_between(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_remove(&vec, 1); + check_strvec(&vec, "foo", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__pop_empty_array(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pop(&vec); + check_strvec(&vec, NULL); + strvec_clear(&vec); +} + +void test_strvec__pop_non_empty_array(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_pushl(&vec, "foo", "bar", "baz", NULL); + strvec_pop(&vec); + check_strvec(&vec, "foo", "bar", NULL); + strvec_clear(&vec); +} + +void test_strvec__split_empty_string(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_split(&vec, ""); + check_strvec(&vec, NULL); + strvec_clear(&vec); +} + +void test_strvec__split_single_item(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_split(&vec, "foo"); + check_strvec(&vec, "foo", NULL); + strvec_clear(&vec); +} + +void test_strvec__split_multiple_items(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_split(&vec, "foo bar baz"); + check_strvec(&vec, "foo", "bar", "baz", NULL); + strvec_clear(&vec); +} + +void test_strvec__split_whitespace_only(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_split(&vec, " \t\n"); + check_strvec(&vec, NULL); + strvec_clear(&vec); +} + +void test_strvec__split_multiple_consecutive_whitespaces(void) +{ + struct strvec vec = STRVEC_INIT; + + strvec_split(&vec, "foo\n\t bar"); + check_strvec(&vec, "foo", "bar", NULL); + strvec_clear(&vec); +} + +void test_strvec__detach(void) +{ + struct strvec vec = STRVEC_INIT; + const char **detached; + + strvec_push(&vec, "foo"); + + detached = strvec_detach(&vec); + cl_assert_equal_s(detached[0], "foo"); + cl_assert_equal_p(detached[1], NULL); + + cl_assert_equal_p(vec.v, empty_strvec); + cl_assert_equal_i(vec.nr, 0); + cl_assert_equal_i(vec.alloc, 0); + + free((char *) detached[0]); + free(detached); +} diff --git a/t/unit-tests/t-example-decorate.c b/t/unit-tests/t-example-decorate.c index a4a75db735..8bf0709c41 100644 --- a/t/unit-tests/t-example-decorate.c +++ b/t/unit-tests/t-example-decorate.c @@ -15,36 +15,29 @@ static void t_add(struct test_vars *vars) { void *ret = add_decoration(&vars->n, vars->one, &vars->decoration_a); - if (!check(ret == NULL)) - test_msg("when adding a brand-new object, NULL should be returned"); + check(ret == NULL); ret = add_decoration(&vars->n, vars->two, NULL); - if (!check(ret == NULL)) - test_msg("when adding a brand-new object, NULL should be returned"); + check(ret == NULL); } static void t_readd(struct test_vars *vars) { void *ret = add_decoration(&vars->n, vars->one, NULL); - if (!check(ret == &vars->decoration_a)) - test_msg("when readding an already existing object, existing decoration should be returned"); + check(ret == &vars->decoration_a); ret = add_decoration(&vars->n, vars->two, &vars->decoration_b); - if (!check(ret == NULL)) - test_msg("when readding an already existing object, existing decoration should be returned"); + check(ret == NULL); } static void t_lookup(struct test_vars *vars) { void *ret = lookup_decoration(&vars->n, vars->one); - if (!check(ret == NULL)) - test_msg("lookup should return added declaration"); + check(ret == NULL); ret = lookup_decoration(&vars->n, vars->two); - if (!check(ret == &vars->decoration_b)) - test_msg("lookup should return added declaration"); + check(ret == &vars->decoration_b); ret = lookup_decoration(&vars->n, vars->three); - if (!check(ret == NULL)) - test_msg("lookup for unknown object should return NULL"); + check(ret == NULL); } static void t_loop(struct test_vars *vars) @@ -55,8 +48,7 @@ static void t_loop(struct test_vars *vars) if (vars->n.entries[i].base) objects_noticed++; } - if (!check_int(objects_noticed, ==, 2)) - test_msg("should have 2 objects"); + check_int(objects_noticed, ==, 2); } int cmd_main(int argc UNUSED, const char **argv UNUSED) diff --git a/t/unit-tests/t-hash.c b/t/unit-tests/t-hash.c index e9a78bf2c0..e62647019b 100644 --- a/t/unit-tests/t-hash.c +++ b/t/unit-tests/t-hash.c @@ -38,7 +38,7 @@ static void check_hash_data(const void *data, size_t data_length, "SHA1 and SHA256 (%s) works", #literal); \ } while (0) -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT; struct strbuf alphabet_100000 = STRBUF_INIT; diff --git a/t/unit-tests/t-hashmap.c b/t/unit-tests/t-hashmap.c new file mode 100644 index 0000000000..83b79dff39 --- /dev/null +++ b/t/unit-tests/t-hashmap.c @@ -0,0 +1,361 @@ +#include "test-lib.h" +#include "hashmap.h" +#include "strbuf.h" + +struct test_entry { + int padding; /* hashmap entry no longer needs to be the first member */ + struct hashmap_entry ent; + /* key and value as two \0-terminated strings */ + char key[FLEX_ARRAY]; +}; + +static int test_entry_cmp(const void *cmp_data, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, + const void *keydata) +{ + const unsigned int ignore_case = cmp_data ? *((int *)cmp_data) : 0; + const struct test_entry *e1, *e2; + const char *key = keydata; + + e1 = container_of(eptr, const struct test_entry, ent); + e2 = container_of(entry_or_key, const struct test_entry, ent); + + if (ignore_case) + return strcasecmp(e1->key, key ? key : e2->key); + else + return strcmp(e1->key, key ? key : e2->key); +} + +static const char *get_value(const struct test_entry *e) +{ + return e->key + strlen(e->key) + 1; +} + +static struct test_entry *alloc_test_entry(const char *key, const char *value, + unsigned int ignore_case) +{ + size_t klen = strlen(key); + size_t vlen = strlen(value); + unsigned int hash = ignore_case ? strihash(key) : strhash(key); + struct test_entry *entry = xmalloc(st_add4(sizeof(*entry), klen, vlen, 2)); + + hashmap_entry_init(&entry->ent, hash); + memcpy(entry->key, key, klen + 1); + memcpy(entry->key + klen + 1, value, vlen + 1); + return entry; +} + +static struct test_entry *get_test_entry(struct hashmap *map, const char *key, + unsigned int ignore_case) +{ + return hashmap_get_entry_from_hash( + map, ignore_case ? strihash(key) : strhash(key), key, + struct test_entry, ent); +} + +static int key_val_contains(const char *key_val[][2], char seen[], size_t n, + struct test_entry *entry) +{ + for (size_t i = 0; i < n; i++) { + if (!strcmp(entry->key, key_val[i][0]) && + !strcmp(get_value(entry), key_val[i][1])) { + if (seen[i]) + return 2; + seen[i] = 1; + return 0; + } + } + return 1; +} + +static void setup(void (*f)(struct hashmap *map, unsigned int ignore_case), + unsigned int ignore_case) +{ + struct hashmap map = HASHMAP_INIT(test_entry_cmp, &ignore_case); + + f(&map, ignore_case); + hashmap_clear_and_free(&map, struct test_entry, ent); +} + +static void t_replace(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry; + + entry = alloc_test_entry("key1", "value1", ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + + entry = alloc_test_entry(ignore_case ? "Key1" : "key1", "value2", + ignore_case); + entry = hashmap_put_entry(map, entry, ent); + if (check(entry != NULL)) + check_str(get_value(entry), "value1"); + free(entry); + + entry = alloc_test_entry("fooBarFrotz", "value3", ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + + entry = alloc_test_entry(ignore_case ? "FOObarFrotz" : "fooBarFrotz", + "value4", ignore_case); + entry = hashmap_put_entry(map, entry, ent); + if (check(entry != NULL)) + check_str(get_value(entry), "value3"); + free(entry); +} + +static void t_get(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry; + const char *key_val[][2] = { { "key1", "value1" }, + { "key2", "value2" }, + { "fooBarFrotz", "value3" }, + { ignore_case ? "key4" : "foobarfrotz", + "value4" } }; + const char *query[][2] = { + { ignore_case ? "Key1" : "key1", "value1" }, + { ignore_case ? "keY2" : "key2", "value2" }, + { ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value3" }, + { ignore_case ? "FOObarFrotz" : "foobarfrotz", + ignore_case ? "value3" : "value4" } + }; + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + entry = alloc_test_entry(key_val[i][0], key_val[i][1], + ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + } + + for (size_t i = 0; i < ARRAY_SIZE(query); i++) { + entry = get_test_entry(map, query[i][0], ignore_case); + if (check(entry != NULL)) + check_str(get_value(entry), query[i][1]); + else + test_msg("query key: %s", query[i][0]); + } + + check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); + check_int(map->tablesize, ==, 64); + check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); +} + +static void t_add(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry; + const char *key_val[][2] = { + { "key1", "value1" }, + { ignore_case ? "Key1" : "key1", "value2" }, + { "fooBarFrotz", "value3" }, + { ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value4" } + }; + const char *query_keys[] = { "key1", ignore_case ? "FOObarFrotz" : + "fooBarFrotz" }; + char seen[ARRAY_SIZE(key_val)] = { 0 }; + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); + hashmap_add(map, &entry->ent); + } + + for (size_t i = 0; i < ARRAY_SIZE(query_keys); i++) { + int count = 0; + entry = hashmap_get_entry_from_hash(map, + ignore_case ? strihash(query_keys[i]) : + strhash(query_keys[i]), + query_keys[i], struct test_entry, ent); + + hashmap_for_each_entry_from(map, entry, ent) + { + int ret; + if (!check_int((ret = key_val_contains( + key_val, seen, + ARRAY_SIZE(key_val), entry)), + ==, 0)) { + switch (ret) { + case 1: + test_msg("found entry was not given in the input\n" + " key: %s\n value: %s", + entry->key, get_value(entry)); + break; + case 2: + test_msg("duplicate entry detected\n" + " key: %s\n value: %s", + entry->key, get_value(entry)); + break; + } + } else { + count++; + } + } + check_int(count, ==, 2); + } + + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { + if (!check_int(seen[i], ==, 1)) + test_msg("following key-val pair was not iterated over:\n" + " key: %s\n value: %s", + key_val[i][0], key_val[i][1]); + } + + check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); + check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); +} + +static void t_remove(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry, *removed; + const char *key_val[][2] = { { "key1", "value1" }, + { "key2", "value2" }, + { "fooBarFrotz", "value3" } }; + const char *remove[][2] = { { ignore_case ? "Key1" : "key1", "value1" }, + { ignore_case ? "keY2" : "key2", "value2" } }; + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + } + + for (size_t i = 0; i < ARRAY_SIZE(remove); i++) { + entry = alloc_test_entry(remove[i][0], "", ignore_case); + removed = hashmap_remove_entry(map, entry, ent, remove[i][0]); + if (check(removed != NULL)) + check_str(get_value(removed), remove[i][1]); + free(entry); + free(removed); + } + + entry = alloc_test_entry("notInMap", "", ignore_case); + check_pointer_eq(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL); + free(entry); + + check_int(map->tablesize, ==, 64); + check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val) - ARRAY_SIZE(remove)); +} + +static void t_iterate(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry; + struct hashmap_iter iter; + const char *key_val[][2] = { { "key1", "value1" }, + { "key2", "value2" }, + { "fooBarFrotz", "value3" } }; + char seen[ARRAY_SIZE(key_val)] = { 0 }; + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + } + + hashmap_for_each_entry(map, &iter, entry, ent /* member name */) + { + int ret; + if (!check_int((ret = key_val_contains(key_val, seen, + ARRAY_SIZE(key_val), + entry)), ==, 0)) { + switch (ret) { + case 1: + test_msg("found entry was not given in the input\n" + " key: %s\n value: %s", + entry->key, get_value(entry)); + break; + case 2: + test_msg("duplicate entry detected\n" + " key: %s\n value: %s", + entry->key, get_value(entry)); + break; + } + } + } + + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { + if (!check_int(seen[i], ==, 1)) + test_msg("following key-val pair was not iterated over:\n" + " key: %s\n value: %s", + key_val[i][0], key_val[i][1]); + } + + check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); +} + +static void t_alloc(struct hashmap *map, unsigned int ignore_case) +{ + struct test_entry *entry, *removed; + + for (int i = 1; i <= 51; i++) { + char *key = xstrfmt("key%d", i); + char *value = xstrfmt("value%d", i); + entry = alloc_test_entry(key, value, ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + free(key); + free(value); + } + check_int(map->tablesize, ==, 64); + check_int(hashmap_get_size(map), ==, 51); + + entry = alloc_test_entry("key52", "value52", ignore_case); + check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + check_int(map->tablesize, ==, 256); + check_int(hashmap_get_size(map), ==, 52); + + for (int i = 1; i <= 12; i++) { + char *key = xstrfmt("key%d", i); + char *value = xstrfmt("value%d", i); + + entry = alloc_test_entry(key, "", ignore_case); + removed = hashmap_remove_entry(map, entry, ent, key); + if (check(removed != NULL)) + check_str(value, get_value(removed)); + free(key); + free(value); + free(entry); + free(removed); + } + check_int(map->tablesize, ==, 256); + check_int(hashmap_get_size(map), ==, 40); + + entry = alloc_test_entry("key40", "", ignore_case); + removed = hashmap_remove_entry(map, entry, ent, "key40"); + if (check(removed != NULL)) + check_str("value40", get_value(removed)); + check_int(map->tablesize, ==, 64); + check_int(hashmap_get_size(map), ==, 39); + free(entry); + free(removed); +} + +static void t_intern(void) +{ + const char *values[] = { "value1", "Value1", "value2", "value2" }; + + for (size_t i = 0; i < ARRAY_SIZE(values); i++) { + const char *i1 = strintern(values[i]); + const char *i2 = strintern(values[i]); + + if (!check(!strcmp(i1, values[i]))) + test_msg("strintern(%s) returns %s\n", values[i], i1); + else if (!check(i1 != values[i])) + test_msg("strintern(%s) returns input pointer\n", + values[i]); + else if (!check_pointer_eq(i1, i2)) + test_msg("address('%s') != address('%s'), so strintern('%s') != strintern('%s')", + i1, i2, values[i], values[i]); + else + check_str(i1, values[i]); + } +} + +int cmd_main(int argc UNUSED, const char **argv UNUSED) +{ + TEST(setup(t_replace, 0), "replace works"); + TEST(setup(t_replace, 1), "replace (case insensitive) works"); + TEST(setup(t_get, 0), "get works"); + TEST(setup(t_get, 1), "get (case insensitive) works"); + TEST(setup(t_add, 0), "add works"); + TEST(setup(t_add, 1), "add (case insensitive) works"); + TEST(setup(t_remove, 0), "remove works"); + TEST(setup(t_remove, 1), "remove (case insensitive) works"); + TEST(setup(t_iterate, 0), "iterate works"); + TEST(setup(t_iterate, 1), "iterate (case insensitive) works"); + TEST(setup(t_alloc, 0), "grow / shrink works"); + TEST(t_intern(), "string interning works"); + return test_done(); +} diff --git a/t/unit-tests/t-mem-pool.c b/t/unit-tests/t-mem-pool.c index a0d57df761..fe500c704b 100644 --- a/t/unit-tests/t-mem-pool.c +++ b/t/unit-tests/t-mem-pool.c @@ -20,7 +20,7 @@ static void t_calloc_100(struct mem_pool *pool) check(pool->mp_block->end != NULL); } -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { TEST(setup_static(t_calloc_100, 1024 * 1024), "mem_pool_calloc returns 100 zeroed bytes with big block"); diff --git a/t/unit-tests/t-oid-array.c b/t/unit-tests/t-oid-array.c new file mode 100644 index 0000000000..45b59a2a51 --- /dev/null +++ b/t/unit-tests/t-oid-array.c @@ -0,0 +1,126 @@ +#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-prio-queue.c b/t/unit-tests/t-prio-queue.c index 7a4e5780e1..fe6ae37935 100644 --- a/t/unit-tests/t-prio-queue.c +++ b/t/unit-tests/t-prio-queue.c @@ -69,7 +69,7 @@ static void test_prio_queue(int *input, size_t input_size, #define TEST_INPUT(input, result) \ test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { TEST(TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }), ((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 })), diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 4e80bdf16d..65d50df091 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -20,141 +20,126 @@ static int integer_needle_lesseq(size_t i, void *_args) return args->needle <= args->haystack[i]; } -static void test_binsearch(void) +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { - int haystack[] = { 2, 4, 6, 8, 10 }; - struct { - int needle; - size_t expected_idx; - } testcases[] = { - {-9000, 0}, - {-1, 0}, - {0, 0}, - {2, 0}, - {3, 1}, - {4, 1}, - {7, 3}, - {9, 4}, - {10, 4}, - {11, 5}, - {9000, 5}, - }; - - for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { - struct integer_needle_lesseq_args args = { - .haystack = haystack, - .needle = testcases[i].needle, + if_test ("binary search with binsearch works") { + int haystack[] = { 2, 4, 6, 8, 10 }; + struct { + int needle; + size_t expected_idx; + } testcases[] = { + {-9000, 0}, + {-1, 0}, + {0, 0}, + {2, 0}, + {3, 1}, + {4, 1}, + {7, 3}, + {9, 4}, + {10, 4}, + {11, 5}, + {9000, 5}, }; - size_t idx; - idx = binsearch(ARRAY_SIZE(haystack), &integer_needle_lesseq, &args); - check_int(idx, ==, testcases[i].expected_idx); + for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { + struct integer_needle_lesseq_args args = { + .haystack = haystack, + .needle = testcases[i].needle, + }; + size_t idx; + + idx = binsearch(ARRAY_SIZE(haystack), + &integer_needle_lesseq, &args); + check_int(idx, ==, testcases[i].expected_idx); + } } -} - -static void test_names_length(void) -{ - const char *a[] = { "a", "b", NULL }; - check_int(names_length(a), ==, 2); -} -static void test_names_equal(void) -{ - const char *a[] = { "a", "b", "c", NULL }; - const char *b[] = { "a", "b", "d", NULL }; - const char *c[] = { "a", "b", NULL }; + if_test ("names_length returns size of a NULL-terminated string array") { + const char *a[] = { "a", "b", NULL }; + check_int(names_length(a), ==, 2); + } - check(names_equal(a, a)); - check(!names_equal(a, b)); - check(!names_equal(a, c)); -} + if_test ("names_equal compares NULL-terminated string arrays") { + const char *a[] = { "a", "b", "c", NULL }; + const char *b[] = { "a", "b", "d", NULL }; + const char *c[] = { "a", "b", NULL }; -static void test_parse_names_normal(void) -{ - char in1[] = "line\n"; - char in2[] = "a\nb\nc"; - char **out = NULL; - parse_names(in1, strlen(in1), &out); - check_str(out[0], "line"); - check(!out[1]); - free_names(out); - - parse_names(in2, strlen(in2), &out); - check_str(out[0], "a"); - check_str(out[1], "b"); - check_str(out[2], "c"); - check(!out[3]); - free_names(out); -} + check(names_equal(a, a)); + check(!names_equal(a, b)); + check(!names_equal(a, c)); + } -static void test_parse_names_drop_empty(void) -{ - char in[] = "a\n\nb\n"; - char **out = NULL; - parse_names(in, strlen(in), &out); - check_str(out[0], "a"); - /* simply '\n' should be dropped as empty string */ - check_str(out[1], "b"); - check(!out[2]); - free_names(out); -} + if_test ("parse_names works for basic input") { + char in1[] = "line\n"; + char in2[] = "a\nb\nc"; + char **out = parse_names(in1, strlen(in1)); + check(out != NULL); + check_str(out[0], "line"); + check(!out[1]); + free_names(out); + + out = parse_names(in2, strlen(in2)); + check(out != NULL); + check_str(out[0], "a"); + check_str(out[1], "b"); + check_str(out[2], "c"); + check(!out[3]); + free_names(out); + } -static void test_common_prefix(void) -{ - struct strbuf a = STRBUF_INIT; - struct strbuf b = STRBUF_INIT; - struct { - const char *a, *b; - int want; - } cases[] = { - {"abcdef", "abc", 3}, - { "abc", "ab", 2 }, - { "", "abc", 0 }, - { "abc", "abd", 2 }, - { "abc", "pqr", 0 }, - }; - - for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { - strbuf_addstr(&a, cases[i].a); - strbuf_addstr(&b, cases[i].b); - check_int(common_prefix_size(&a, &b), ==, cases[i].want); - strbuf_reset(&a); - strbuf_reset(&b); + if_test ("parse_names drops empty string") { + char in[] = "a\n\nb\n"; + char **out = parse_names(in, strlen(in)); + check(out != NULL); + check_str(out[0], "a"); + /* simply '\n' should be dropped as empty string */ + check_str(out[1], "b"); + check(!out[2]); + free_names(out); } - strbuf_release(&a); - strbuf_release(&b); -} -static void test_u24_roundtrip(void) -{ - uint32_t in = 0x112233; - uint8_t dest[3]; - uint32_t out; - put_be24(dest, in); - out = get_be24(dest); - check_int(in, ==, out); -} + if_test ("common_prefix_size works") { + struct reftable_buf a = REFTABLE_BUF_INIT; + struct reftable_buf b = REFTABLE_BUF_INIT; + struct { + const char *a, *b; + int want; + } cases[] = { + {"abcdef", "abc", 3}, + { "abc", "ab", 2 }, + { "", "abc", 0 }, + { "abc", "abd", 2 }, + { "abc", "pqr", 0 }, + }; -static void test_u16_roundtrip(void) -{ - uint32_t in = 0xfef1; - uint8_t dest[3]; - uint32_t out; - put_be16(dest, in); - out = get_be16(dest); - check_int(in, ==, out); -} + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + check(!reftable_buf_addstr(&a, cases[i].a)); + check(!reftable_buf_addstr(&b, cases[i].b)); + check_int(common_prefix_size(&a, &b), ==, cases[i].want); + reftable_buf_reset(&a); + reftable_buf_reset(&b); + } + reftable_buf_release(&a); + reftable_buf_release(&b); + } -int cmd_main(int argc, const char *argv[]) -{ - TEST(test_common_prefix(), "common_prefix_size works"); - TEST(test_parse_names_normal(), "parse_names works for basic input"); - TEST(test_parse_names_drop_empty(), "parse_names drops empty string"); - TEST(test_binsearch(), "binary search with binsearch works"); - TEST(test_names_length(), "names_length retuns size of a NULL-terminated string array"); - TEST(test_names_equal(), "names_equal compares NULL-terminated string arrays"); - TEST(test_u24_roundtrip(), "put_be24 and get_be24 work"); - TEST(test_u16_roundtrip(), "put_be16 and get_be16 work"); + if_test ("put_be24 and get_be24 work") { + uint32_t in = 0x112233; + uint8_t dest[3]; + uint32_t out; + put_be24(dest, in); + out = get_be24(dest); + check_int(in, ==, out); + } + + if_test ("put_be16 and get_be16 work") { + uint32_t in = 0xfef1; + uint8_t dest[3]; + uint32_t out; + put_be16(dest, in); + out = get_be16(dest); + check_int(in, ==, out); + } return test_done(); } diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c new file mode 100644 index 0000000000..22040aeefa --- /dev/null +++ b/t/unit-tests/t-reftable-block.c @@ -0,0 +1,383 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "reftable/block.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/reftable-error.h" +#include "strbuf.h" + +static void t_ref_block_read_write(void) +{ + const int header_off = 21; /* random */ + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_REF, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + check(block.data != NULL); + block.len = block_size; + block_source_from_buf(&block.source ,&buf); + ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + check(!ret); + + rec.u.ref.refname = (char *) ""; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + ret = block_writer_add(&bw, &rec); + check_int(ret, ==, REFTABLE_API_ERROR); + + for (i = 0; i < N; i++) { + rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); + rec.u.ref.value_type = REFTABLE_REF_VAL1; + memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.ref.refname = NULL; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + reftable_buf_release(&want); + reftable_buf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_log_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 2048; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_LOG, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + check(block.data != NULL); + block.len = block_size; + block_source_from_buf(&block.source ,&buf); + ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + check(!ret); + + for (i = 0; i < N; i++) { + rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); + rec.u.log.update_index = i; + rec.u.log.value_type = REFTABLE_LOG_UPDATE; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.log.refname = NULL; + rec.u.log.value_type = REFTABLE_LOG_DELETION; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_buf_reset(&want); + check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + reftable_buf_release(&want); + reftable_buf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_obj_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_OBJ, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + check(block.data != NULL); + block.len = block_size; + block_source_from_buf(&block.source, &buf); + ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + check(!ret); + + for (i = 0; i < N; i++) { + uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; + DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes)); + + rec.u.obj.hash_prefix = allocated; + rec.u.obj.hash_prefix_len = 5; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.obj.hash_prefix = NULL; + rec.u.obj.hash_prefix_len = 0; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + reftable_buf_release(&want); + reftable_buf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_index_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_INDEX, + .u.idx.last_key = REFTABLE_BUF_INIT, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + check(block.data != NULL); + block.len = block_size; + block_source_from_buf(&block.source, &buf); + ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + check(!ret); + + for (i = 0; i < N; i++) { + char buf[128]; + + snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); + + reftable_buf_init(&recs[i].u.idx.last_key); + recs[i].type = BLOCK_TYPE_INDEX; + check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); + recs[i].u.idx.offset = i; + + ret = block_writer_add(&bw, &recs[i]); + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + reftable_buf_release(&want); + reftable_buf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_index_block_read_write(), "read-write operations on index blocks work"); + TEST(t_log_block_read_write(), "read-write operations on log blocks work"); + TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); + TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); + + return test_done(); +} diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c new file mode 100644 index 0000000000..a12bd0e1a3 --- /dev/null +++ b/t/unit-tests/t-reftable-merged.c @@ -0,0 +1,546 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "lib-reftable.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/merged.h" +#include "reftable/reader.h" +#include "reftable/reftable-error.h" +#include "reftable/reftable-merged.h" +#include "reftable/reftable-writer.h" + +static struct reftable_merged_table * +merged_table_from_records(struct reftable_ref_record **refs, + struct reftable_block_source **source, + struct reftable_reader ***readers, const size_t *sizes, + struct reftable_buf *buf, const size_t n) +{ + struct reftable_merged_table *mt = NULL; + struct reftable_write_options opts = { + .block_size = 256, + }; + int err; + + REFTABLE_CALLOC_ARRAY(*readers, n); + check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*source, n); + check(*source != NULL); + + for (size_t i = 0; i < n; i++) { + t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); + block_source_from_buf(&(*source)[i], &buf[i]); + + err = reftable_reader_new(&(*readers)[i], &(*source)[i], + "name"); + check(!err); + } + + err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + check(!err); + return mt; +} + +static void readers_destroy(struct reftable_reader **readers, const size_t n) +{ + for (size_t i = 0; i < n; i++) + reftable_reader_decref(readers[i]); + reftable_free(readers); +} + +static void t_merged_single_record(void) +{ + struct reftable_ref_record r1[] = { { + .refname = (char *) "b", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1, 2, 3, 0 }, + } }; + struct reftable_ref_record r2[] = { { + .refname = (char *) "a", + .update_index = 2, + .value_type = REFTABLE_REF_DELETION, + } }; + struct reftable_ref_record r3[] = { { + .refname = (char *) "c", + .update_index = 3, + .value_type = REFTABLE_REF_DELETION, + } }; + + struct reftable_ref_record *refs[] = { r1, r2, r3 }; + size_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; + struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; + struct reftable_block_source *bs = NULL; + struct reftable_reader **readers = NULL; + struct reftable_merged_table *mt = + merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + int err; + + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + check(!err); + err = reftable_iterator_seek_ref(&it, "a"); + check(!err); + + err = reftable_iterator_next_ref(&it, &ref); + check(!err); + check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + readers_destroy(readers, 3); + reftable_merged_table_free(mt); + for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) + reftable_buf_release(&bufs[i]); + reftable_free(bs); +} + +static void t_merged_refs(void) +{ + struct reftable_ref_record r1[] = { + { + .refname = (char *) "a", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + }, + { + .refname = (char *) "b", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + }, + { + .refname = (char *) "c", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + } + }; + struct reftable_ref_record r2[] = { { + .refname = (char *) "a", + .update_index = 2, + .value_type = REFTABLE_REF_DELETION, + } }; + struct reftable_ref_record r3[] = { + { + .refname = (char *) "c", + .update_index = 3, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 2 }, + }, + { + .refname = (char *) "d", + .update_index = 3, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + }, + }; + + struct reftable_ref_record *want[] = { + &r2[0], + &r1[1], + &r3[0], + &r3[1], + }; + + struct reftable_ref_record *refs[] = { r1, r2, r3 }; + size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; + struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; + struct reftable_block_source *bs = NULL; + struct reftable_reader **readers = NULL; + struct reftable_merged_table *mt = + merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + struct reftable_iterator it = { 0 }; + int err; + struct reftable_ref_record *out = NULL; + size_t len = 0; + size_t cap = 0; + size_t i; + + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + check(!err); + err = reftable_iterator_seek_ref(&it, "a"); + check(!err); + check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); + check_int(reftable_merged_table_min_update_index(mt), ==, 1); + check_int(reftable_merged_table_max_update_index(mt), ==, 3); + + while (len < 100) { /* cap loops/recursion. */ + struct reftable_ref_record ref = { 0 }; + int err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) + break; + + REFTABLE_ALLOC_GROW(out, len + 1, cap); + out[len++] = ref; + } + reftable_iterator_destroy(&it); + + check_int(ARRAY_SIZE(want), ==, len); + for (i = 0; i < len; i++) + check(reftable_ref_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1)); + for (i = 0; i < len; i++) + reftable_ref_record_release(&out[i]); + reftable_free(out); + + for (i = 0; i < 3; i++) + reftable_buf_release(&bufs[i]); + readers_destroy(readers, 3); + reftable_merged_table_free(mt); + reftable_free(bs); +} + +static void t_merged_seek_multiple_times(void) +{ + struct reftable_ref_record r1[] = { + { + .refname = (char *) "a", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + }, + { + .refname = (char *) "c", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 2 }, + } + }; + struct reftable_ref_record r2[] = { + { + .refname = (char *) "b", + .update_index = 2, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 3 }, + }, + { + .refname = (char *) "d", + .update_index = 2, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 4 }, + }, + }; + struct reftable_ref_record *refs[] = { + r1, r2, + }; + size_t sizes[] = { + ARRAY_SIZE(r1), ARRAY_SIZE(r2), + }; + struct reftable_buf bufs[] = { + REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, + }; + struct reftable_block_source *sources = NULL; + struct reftable_reader **readers = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_merged_table *mt; + + mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); + merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + + for (size_t i = 0; i < 5; i++) { + int err = reftable_iterator_seek_ref(&it, "c"); + check(!err); + + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + err = reftable_ref_record_equal(&rec, &r1[1], REFTABLE_HASH_SIZE_SHA1); + check(err == 1); + + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + err = reftable_ref_record_equal(&rec, &r2[1], REFTABLE_HASH_SIZE_SHA1); + check(err == 1); + + err = reftable_iterator_next_ref(&it, &rec); + check(err > 0); + } + + for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) + reftable_buf_release(&bufs[i]); + readers_destroy(readers, ARRAY_SIZE(refs)); + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_merged_table_free(mt); + reftable_free(sources); +} + +static void t_merged_seek_multiple_times_without_draining(void) +{ + struct reftable_ref_record r1[] = { + { + .refname = (char *) "a", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 1 }, + }, + { + .refname = (char *) "c", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 2 }, + } + }; + struct reftable_ref_record r2[] = { + { + .refname = (char *) "b", + .update_index = 2, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 3 }, + }, + { + .refname = (char *) "d", + .update_index = 2, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 4 }, + }, + }; + struct reftable_ref_record *refs[] = { + r1, r2, + }; + size_t sizes[] = { + ARRAY_SIZE(r1), ARRAY_SIZE(r2), + }; + struct reftable_buf bufs[] = { + REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, + }; + struct reftable_block_source *sources = NULL; + struct reftable_reader **readers = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_merged_table *mt; + int err; + + mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); + merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + + err = reftable_iterator_seek_ref(&it, "b"); + check(!err); + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + err = reftable_ref_record_equal(&rec, &r2[0], REFTABLE_HASH_SIZE_SHA1); + check(err == 1); + + err = reftable_iterator_seek_ref(&it, "a"); + check(!err); + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + err = reftable_ref_record_equal(&rec, &r1[0], REFTABLE_HASH_SIZE_SHA1); + check(err == 1); + + for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) + reftable_buf_release(&bufs[i]); + readers_destroy(readers, ARRAY_SIZE(refs)); + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_merged_table_free(mt); + reftable_free(sources); +} + +static struct reftable_merged_table * +merged_table_from_log_records(struct reftable_log_record **logs, + struct reftable_block_source **source, + struct reftable_reader ***readers, const size_t *sizes, + struct reftable_buf *buf, const size_t n) +{ + struct reftable_merged_table *mt = NULL; + struct reftable_write_options opts = { + .block_size = 256, + .exact_log_message = 1, + }; + int err; + + REFTABLE_CALLOC_ARRAY(*readers, n); + check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*source, n); + check(*source != NULL); + + for (size_t i = 0; i < n; i++) { + t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); + block_source_from_buf(&(*source)[i], &buf[i]); + + err = reftable_reader_new(&(*readers)[i], &(*source)[i], + "name"); + check(!err); + } + + err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + check(!err); + return mt; +} + +static void t_merged_logs(void) +{ + struct reftable_log_record r1[] = { + { + .refname = (char *) "a", + .update_index = 2, + .value_type = REFTABLE_LOG_UPDATE, + .value.update = { + .old_hash = { 2 }, + /* deletion */ + .name = (char *) "jane doe", + .email = (char *) "jane@invalid", + .message = (char *) "message2", + } + }, + { + .refname = (char *) "a", + .update_index = 1, + .value_type = REFTABLE_LOG_UPDATE, + .value.update = { + .old_hash = { 1 }, + .new_hash = { 2 }, + .name = (char *) "jane doe", + .email = (char *) "jane@invalid", + .message = (char *) "message1", + } + }, + }; + struct reftable_log_record r2[] = { + { + .refname = (char *) "a", + .update_index = 3, + .value_type = REFTABLE_LOG_UPDATE, + .value.update = { + .new_hash = { 3 }, + .name = (char *) "jane doe", + .email = (char *) "jane@invalid", + .message = (char *) "message3", + } + }, + }; + struct reftable_log_record r3[] = { + { + .refname = (char *) "a", + .update_index = 2, + .value_type = REFTABLE_LOG_DELETION, + }, + }; + struct reftable_log_record *want[] = { + &r2[0], + &r3[0], + &r1[1], + }; + + struct reftable_log_record *logs[] = { r1, r2, r3 }; + size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; + struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; + struct reftable_block_source *bs = NULL; + struct reftable_reader **readers = NULL; + struct reftable_merged_table *mt = merged_table_from_log_records( + logs, &bs, &readers, sizes, bufs, 3); + struct reftable_iterator it = { 0 }; + int err; + struct reftable_log_record *out = NULL; + size_t len = 0; + size_t cap = 0; + size_t i; + + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + check(!err); + err = reftable_iterator_seek_log(&it, "a"); + check(!err); + check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); + check_int(reftable_merged_table_min_update_index(mt), ==, 1); + check_int(reftable_merged_table_max_update_index(mt), ==, 3); + + while (len < 100) { /* cap loops/recursion. */ + struct reftable_log_record log = { 0 }; + int err = reftable_iterator_next_log(&it, &log); + if (err > 0) + break; + + REFTABLE_ALLOC_GROW(out, len + 1, cap); + out[len++] = log; + } + reftable_iterator_destroy(&it); + + check_int(ARRAY_SIZE(want), ==, len); + for (i = 0; i < len; i++) + check(reftable_log_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1)); + + err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + check(!err); + err = reftable_iterator_seek_log_at(&it, "a", 2); + check(!err); + reftable_log_record_release(&out[0]); + err = reftable_iterator_next_log(&it, &out[0]); + check(!err); + check(reftable_log_record_equal(&out[0], &r3[0], REFTABLE_HASH_SIZE_SHA1)); + reftable_iterator_destroy(&it); + + for (i = 0; i < len; i++) + reftable_log_record_release(&out[i]); + reftable_free(out); + + for (i = 0; i < 3; i++) + reftable_buf_release(&bufs[i]); + readers_destroy(readers, 3); + reftable_merged_table_free(mt); + reftable_free(bs); +} + +static void t_default_write_opts(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_ref_record rec = { + .refname = (char *) "master", + .update_index = 1, + }; + int err; + struct reftable_block_source source = { 0 }; + uint32_t hash_id; + struct reftable_reader *rd = NULL; + struct reftable_merged_table *merged = NULL; + + reftable_writer_set_limits(w, 1, 1); + + err = reftable_writer_add_ref(w, &rec); + check(!err); + + err = reftable_writer_close(w); + check(!err); + reftable_writer_free(w); + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&rd, &source, "filename"); + check(!err); + + hash_id = reftable_reader_hash_id(rd); + check_int(hash_id, ==, REFTABLE_HASH_SHA1); + + err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA256); + check_int(err, ==, REFTABLE_FORMAT_ERROR); + err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA1); + check(!err); + + reftable_reader_decref(rd); + reftable_merged_table_free(merged); + reftable_buf_release(&buf); +} + + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_default_write_opts(), "merged table with default write opts"); + TEST(t_merged_logs(), "merged table with multiple log updates for same ref"); + TEST(t_merged_refs(), "merged table with multiple updates to same ref"); + TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times"); + TEST(t_merged_seek_multiple_times_without_draining(), "merged table can seek multiple times without draining"); + TEST(t_merged_single_record(), "ref occurring in only one record can be fetched"); + + return test_done(); +} diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c new file mode 100644 index 0000000000..f3f8a0cdf3 --- /dev/null +++ b/t/unit-tests/t-reftable-pq.c @@ -0,0 +1,153 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "reftable/constants.h" +#include "reftable/pq.h" +#include "strbuf.h" + +static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) +{ + for (size_t i = 1; i < pq->len; i++) { + size_t parent = (i - 1) / 2; + check(pq_less(&pq->heap[parent], &pq->heap[i])); + } +} + +static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b) +{ + return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index); +} + +static void t_pq_record(void) +{ + struct merged_iter_pqueue pq = { 0 }; + struct reftable_record recs[54]; + size_t N = ARRAY_SIZE(recs) - 1, i; + char *last = NULL; + + for (i = 0; i < N; i++) { + reftable_record_init(&recs[i], BLOCK_TYPE_REF); + recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i); + } + + i = 1; + do { + struct pq_entry e = { + .rec = &recs[i], + }; + + merged_iter_pqueue_add(&pq, &e); + merged_iter_pqueue_check(&pq); + i = (i * 7) % N; + } while (i != 1); + + while (!merged_iter_pqueue_is_empty(pq)) { + struct pq_entry top = merged_iter_pqueue_top(pq); + struct pq_entry e = merged_iter_pqueue_remove(&pq); + merged_iter_pqueue_check(&pq); + + check(pq_entry_equal(&top, &e)); + check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + if (last) + check_int(strcmp(last, e.rec->u.ref.refname), <, 0); + last = e.rec->u.ref.refname; + } + + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); + merged_iter_pqueue_release(&pq); +} + +static void t_pq_index(void) +{ + struct merged_iter_pqueue pq = { 0 }; + struct reftable_record recs[13]; + char *last = NULL; + size_t N = ARRAY_SIZE(recs), i; + + for (i = 0; i < N; i++) { + reftable_record_init(&recs[i], BLOCK_TYPE_REF); + recs[i].u.ref.refname = (char *) "refs/heads/master"; + } + + i = 1; + do { + struct pq_entry e = { + .rec = &recs[i], + .index = i, + }; + + merged_iter_pqueue_add(&pq, &e); + merged_iter_pqueue_check(&pq); + i = (i * 7) % N; + } while (i != 1); + + for (i = N - 1; i > 0; i--) { + struct pq_entry top = merged_iter_pqueue_top(pq); + struct pq_entry e = merged_iter_pqueue_remove(&pq); + merged_iter_pqueue_check(&pq); + + check(pq_entry_equal(&top, &e)); + check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + check_int(e.index, ==, i); + if (last) + check_str(last, e.rec->u.ref.refname); + last = e.rec->u.ref.refname; + } + + merged_iter_pqueue_release(&pq); +} + +static void t_merged_iter_pqueue_top(void) +{ + struct merged_iter_pqueue pq = { 0 }; + struct reftable_record recs[13]; + size_t N = ARRAY_SIZE(recs), i; + + for (i = 0; i < N; i++) { + reftable_record_init(&recs[i], BLOCK_TYPE_REF); + recs[i].u.ref.refname = (char *) "refs/heads/master"; + } + + i = 1; + do { + struct pq_entry e = { + .rec = &recs[i], + .index = i, + }; + + merged_iter_pqueue_add(&pq, &e); + merged_iter_pqueue_check(&pq); + i = (i * 7) % N; + } while (i != 1); + + for (i = N - 1; i > 0; i--) { + struct pq_entry top = merged_iter_pqueue_top(pq); + struct pq_entry e = merged_iter_pqueue_remove(&pq); + + merged_iter_pqueue_check(&pq); + check(pq_entry_equal(&top, &e)); + check(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1)); + for (size_t j = 0; i < pq.len; j++) { + check(pq_less(&top, &pq.heap[j])); + check_int(top.index, >, j); + } + } + + merged_iter_pqueue_release(&pq); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_pq_record(), "pq works with record-based comparison"); + TEST(t_pq_index(), "pq works with index-based comparison"); + TEST(t_merged_iter_pqueue_top(), "merged_iter_pqueue_top works"); + + return test_done(); +} diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c new file mode 100644 index 0000000000..546df6005e --- /dev/null +++ b/t/unit-tests/t-reftable-reader.c @@ -0,0 +1,96 @@ +#include "test-lib.h" +#include "lib-reftable.h" +#include "reftable/blocksource.h" +#include "reftable/reader.h" + +static int t_reader_seek_once(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_reader *reader; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_reader_new(&reader, &source, "name"); + check(!ret); + + reftable_reader_init_ref_iterator(reader, &it); + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); + reftable_buf_release(&buf); + return 0; +} + +static int t_reader_reseek(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_reader *reader; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_reader_new(&reader, &source, "name"); + check(!ret); + + reftable_reader_init_ref_iterator(reader, &it); + + for (size_t i = 0; i < 5; i++) { + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + } + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); + reftable_buf_release(&buf); + return 0; +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_reader_seek_once(), "reader can seek once"); + TEST(t_reader_reseek(), "reader can reseek multiple times"); + return test_done(); +} diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c new file mode 100644 index 0000000000..91c881aedf --- /dev/null +++ b/t/unit-tests/t-reftable-readwrite.c @@ -0,0 +1,940 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "lib-reftable.h" +#include "reftable/basics.h" +#include "reftable/blocksource.h" +#include "reftable/reader.h" +#include "reftable/reftable-error.h" +#include "reftable/reftable-writer.h" +#include "strbuf.h" + +static const int update_index = 5; + +static void t_buffer(void) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_block_source source = { 0 }; + struct reftable_block out = { 0 }; + int n; + uint8_t in[] = "hello"; + check(!reftable_buf_add(&buf, in, sizeof(in))); + block_source_from_buf(&source, &buf); + check_int(block_source_size(&source), ==, 6); + n = block_source_read_block(&source, &out, 0, sizeof(in)); + check_int(n, ==, sizeof(in)); + check(!memcmp(in, out.data, n)); + reftable_block_done(&out); + + n = block_source_read_block(&source, &out, 1, 2); + check_int(n, ==, 2); + check(!memcmp(out.data, "el", 2)); + + reftable_block_done(&out); + block_source_close(&source); + reftable_buf_release(&buf); +} + +static void write_table(char ***names, struct reftable_buf *buf, int N, + int block_size, enum reftable_hash hash_id) +{ + struct reftable_write_options opts = { + .block_size = block_size, + .hash_id = hash_id, + }; + struct reftable_ref_record *refs; + struct reftable_log_record *logs; + int i; + + REFTABLE_CALLOC_ARRAY(*names, N + 1); + check(*names != NULL); + REFTABLE_CALLOC_ARRAY(refs, N); + check(refs != NULL); + REFTABLE_CALLOC_ARRAY(logs, N); + check(logs != NULL); + + for (i = 0; i < N; i++) { + refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i); + refs[i].update_index = update_index; + refs[i].value_type = REFTABLE_REF_VAL1; + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + } + + for (i = 0; i < N; i++) { + logs[i].refname = (*names)[i]; + logs[i].update_index = update_index; + logs[i].value_type = REFTABLE_LOG_UPDATE; + t_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); + logs[i].value.update.message = (char *) "message"; + } + + t_reftable_write_to_buf(buf, refs, N, logs, N, &opts); + + reftable_free(refs); + reftable_free(logs); +} + +static void t_log_buffer_size(void) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_write_options opts = { + .block_size = 4096, + }; + int err; + int i; + struct reftable_log_record + log = { .refname = (char *) "refs/heads/master", + .update_index = 0xa, + .value_type = REFTABLE_LOG_UPDATE, + .value = { .update = { + .name = (char *) "Han-Wen Nienhuys", + .email = (char *) "hanwen@google.com", + .tz_offset = 100, + .time = 0x5e430672, + .message = (char *) "commit: 9\n", + } } }; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + + /* This tests buffer extension for log compression. Must use a random + hash, to ensure that the compressed part is larger than the original. + */ + for (i = 0; i < REFTABLE_HASH_SIZE_SHA1; i++) { + log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); + log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); + } + reftable_writer_set_limits(w, update_index, update_index); + err = reftable_writer_add_log(w, &log); + check(!err); + err = reftable_writer_close(w); + check(!err); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_log_overflow(void) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + char msg[256] = { 0 }; + struct reftable_write_options opts = { + .block_size = ARRAY_SIZE(msg), + }; + int err; + struct reftable_log_record log = { + .refname = (char *) "refs/heads/master", + .update_index = 0xa, + .value_type = REFTABLE_LOG_UPDATE, + .value = { + .update = { + .old_hash = { 1 }, + .new_hash = { 2 }, + .name = (char *) "Han-Wen Nienhuys", + .email = (char *) "hanwen@google.com", + .tz_offset = 100, + .time = 0x5e430672, + .message = msg, + }, + }, + }; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + + memset(msg, 'x', sizeof(msg) - 1); + reftable_writer_set_limits(w, update_index, update_index); + err = reftable_writer_add_log(w, &log); + check_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_log_write_read(void) +{ + struct reftable_write_options opts = { + .block_size = 256, + }; + struct reftable_ref_record ref = { 0 }; + struct reftable_log_record log = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_reader *reader; + struct reftable_block_source source = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + const struct reftable_stats *stats = NULL; + int N = 2, err, i, n; + char **names; + + names = reftable_calloc(N + 1, sizeof(*names)); + check(names != NULL); + + reftable_writer_set_limits(w, 0, N); + + for (i = 0; i < N; i++) { + char name[256]; + struct reftable_ref_record ref = { 0 }; + snprintf(name, sizeof(name), "b%02d%0*d", i, 130, 7); + names[i] = xstrdup(name); + ref.refname = name; + ref.update_index = i; + + err = reftable_writer_add_ref(w, &ref); + check(!err); + } + + for (i = 0; i < N; i++) { + struct reftable_log_record log = { 0 }; + + log.refname = names[i]; + log.update_index = i; + log.value_type = REFTABLE_LOG_UPDATE; + t_reftable_set_hash(log.value.update.old_hash, i, + REFTABLE_HASH_SHA1); + t_reftable_set_hash(log.value.update.new_hash, i + 1, + REFTABLE_HASH_SHA1); + + err = reftable_writer_add_log(w, &log); + check(!err); + } + + n = reftable_writer_close(w); + check_int(n, ==, 0); + + stats = reftable_writer_stats(w); + check_int(stats->log_stats.blocks, >, 0); + reftable_writer_free(w); + w = NULL; + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.log"); + check(!err); + + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + + err = reftable_iterator_seek_ref(&it, names[N - 1]); + check(!err); + + err = reftable_iterator_next_ref(&it, &ref); + check(!err); + + /* end of iteration. */ + err = reftable_iterator_next_ref(&it, &ref); + check_int(err, >, 0); + + reftable_iterator_destroy(&it); + reftable_ref_record_release(&ref); + + err = reftable_reader_init_log_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_log(&it, ""); + check(!err); + + for (i = 0; ; i++) { + int err = reftable_iterator_next_log(&it, &log); + if (err > 0) + break; + check(!err); + check_str(names[i], log.refname); + check_int(i, ==, log.update_index); + reftable_log_record_release(&log); + } + + check_int(i, ==, N); + reftable_iterator_destroy(&it); + + /* cleanup. */ + reftable_buf_release(&buf); + free_names(names); + reftable_reader_decref(reader); +} + +static void t_log_zlib_corruption(void) +{ + struct reftable_write_options opts = { + .block_size = 256, + }; + struct reftable_iterator it = { 0 }; + struct reftable_reader *reader; + struct reftable_block_source source = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + const struct reftable_stats *stats = NULL; + char message[100] = { 0 }; + int err, i, n; + struct reftable_log_record log = { + .refname = (char *) "refname", + .value_type = REFTABLE_LOG_UPDATE, + .value = { + .update = { + .new_hash = { 1 }, + .old_hash = { 2 }, + .name = (char *) "My Name", + .email = (char *) "myname@invalid", + .message = message, + }, + }, + }; + + for (i = 0; i < sizeof(message) - 1; i++) + message[i] = (uint8_t)(git_rand() % 64 + ' '); + + reftable_writer_set_limits(w, 1, 1); + + err = reftable_writer_add_log(w, &log); + check(!err); + + n = reftable_writer_close(w); + check_int(n, ==, 0); + + stats = reftable_writer_stats(w); + check_int(stats->log_stats.blocks, >, 0); + reftable_writer_free(w); + w = NULL; + + /* corrupt the data. */ + buf.buf[50] ^= 0x99; + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.log"); + check(!err); + + err = reftable_reader_init_log_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_log(&it, "refname"); + check_int(err, ==, REFTABLE_ZLIB_ERROR); + + reftable_iterator_destroy(&it); + + /* cleanup. */ + reftable_reader_decref(reader); + reftable_buf_release(&buf); +} + +static void t_table_read_write_sequential(void) +{ + char **names; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int N = 50; + struct reftable_iterator it = { 0 }; + struct reftable_block_source source = { 0 }; + struct reftable_reader *reader; + int err = 0; + int j = 0; + + write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.ref"); + check(!err); + + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, ""); + check(!err); + + for (j = 0; ; j++) { + struct reftable_ref_record ref = { 0 }; + int r = reftable_iterator_next_ref(&it, &ref); + check_int(r, >=, 0); + if (r > 0) + break; + check_str(names[j], ref.refname); + check_int(update_index, ==, ref.update_index); + reftable_ref_record_release(&ref); + } + check_int(j, ==, N); + + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); + reftable_buf_release(&buf); + free_names(names); +} + +static void t_table_write_small_table(void) +{ + char **names; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int N = 1; + write_table(&names, &buf, N, 4096, REFTABLE_HASH_SHA1); + check_int(buf.len, <, 200); + reftable_buf_release(&buf); + free_names(names); +} + +static void t_table_read_api(void) +{ + char **names; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int N = 50; + struct reftable_reader *reader; + struct reftable_block_source source = { 0 }; + int err; + struct reftable_log_record log = { 0 }; + struct reftable_iterator it = { 0 }; + + write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.ref"); + check(!err); + + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, names[0]); + check(!err); + + err = reftable_iterator_next_log(&it, &log); + check_int(err, ==, REFTABLE_API_ERROR); + + reftable_buf_release(&buf); + free_names(names); + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); + reftable_buf_release(&buf); +} + +static void t_table_read_write_seek(int index, enum reftable_hash hash_id) +{ + char **names; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int N = 50; + struct reftable_reader *reader; + struct reftable_block_source source = { 0 }; + int err; + int i = 0; + + struct reftable_iterator it = { 0 }; + struct reftable_buf pastLast = REFTABLE_BUF_INIT; + struct reftable_ref_record ref = { 0 }; + + write_table(&names, &buf, N, 256, hash_id); + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.ref"); + check(!err); + check_int(hash_id, ==, reftable_reader_hash_id(reader)); + + if (!index) { + reader->ref_offsets.index_offset = 0; + } else { + check_int(reader->ref_offsets.index_offset, >, 0); + } + + for (i = 1; i < N; i++) { + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, names[i]); + check(!err); + err = reftable_iterator_next_ref(&it, &ref); + check(!err); + check_str(names[i], ref.refname); + check_int(REFTABLE_REF_VAL1, ==, ref.value_type); + check_int(i, ==, ref.value.val1[0]); + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + } + + check(!reftable_buf_addstr(&pastLast, names[N - 1])); + check(!reftable_buf_addstr(&pastLast, "/")); + + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, pastLast.buf); + if (err == 0) { + struct reftable_ref_record ref = { 0 }; + int err = reftable_iterator_next_ref(&it, &ref); + check_int(err, >, 0); + } else { + check_int(err, >, 0); + } + + reftable_buf_release(&pastLast); + reftable_iterator_destroy(&it); + + reftable_buf_release(&buf); + free_names(names); + reftable_reader_decref(reader); +} + +static void t_table_read_write_seek_linear(void) +{ + t_table_read_write_seek(0, REFTABLE_HASH_SHA1); +} + +static void t_table_read_write_seek_linear_sha256(void) +{ + t_table_read_write_seek(0, REFTABLE_HASH_SHA256); +} + +static void t_table_read_write_seek_index(void) +{ + t_table_read_write_seek(1, REFTABLE_HASH_SHA1); +} + +static void t_table_refs_for(int indexed) +{ + char **want_names; + int want_names_len = 0; + uint8_t want_hash[REFTABLE_HASH_SIZE_SHA1]; + + struct reftable_write_options opts = { + .block_size = 256, + }; + struct reftable_ref_record ref = { 0 }; + struct reftable_reader *reader; + struct reftable_block_source source = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_iterator it = { 0 }; + int N = 50, n, j, err, i; + + want_names = reftable_calloc(N + 1, sizeof(*want_names)); + check(want_names != NULL); + + t_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); + + for (i = 0; i < N; i++) { + uint8_t hash[REFTABLE_HASH_SIZE_SHA1]; + char fill[51] = { 0 }; + char name[100]; + struct reftable_ref_record ref = { 0 }; + + memset(hash, i, sizeof(hash)); + memset(fill, 'x', 50); + /* Put the variable part in the start */ + snprintf(name, sizeof(name), "br%02d%s", i, fill); + name[40] = 0; + ref.refname = name; + + ref.value_type = REFTABLE_REF_VAL2; + t_reftable_set_hash(ref.value.val2.value, i / 4, + REFTABLE_HASH_SHA1); + t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4, + REFTABLE_HASH_SHA1); + + /* 80 bytes / entry, so 3 entries per block. Yields 17 + */ + /* blocks. */ + n = reftable_writer_add_ref(w, &ref); + check_int(n, ==, 0); + + if (!memcmp(ref.value.val2.value, want_hash, REFTABLE_HASH_SIZE_SHA1) || + !memcmp(ref.value.val2.target_value, want_hash, REFTABLE_HASH_SIZE_SHA1)) + want_names[want_names_len++] = xstrdup(name); + } + + n = reftable_writer_close(w); + check_int(n, ==, 0); + + reftable_writer_free(w); + w = NULL; + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&reader, &source, "file.ref"); + check(!err); + if (!indexed) + reader->obj_offsets.is_present = 0; + + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, ""); + check(!err); + reftable_iterator_destroy(&it); + + err = reftable_reader_refs_for(reader, &it, want_hash); + check(!err); + + for (j = 0; ; j++) { + int err = reftable_iterator_next_ref(&it, &ref); + check_int(err, >=, 0); + if (err > 0) + break; + check_int(j, <, want_names_len); + check_str(ref.refname, want_names[j]); + reftable_ref_record_release(&ref); + } + check_int(j, ==, want_names_len); + + reftable_buf_release(&buf); + free_names(want_names); + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); +} + +static void t_table_refs_for_no_index(void) +{ + t_table_refs_for(0); +} + +static void t_table_refs_for_obj_index(void) +{ + t_table_refs_for(1); +} + +static void t_write_empty_table(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_block_source source = { 0 }; + struct reftable_reader *rd = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + int err; + + reftable_writer_set_limits(w, 1, 1); + + err = reftable_writer_close(w); + check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + reftable_writer_free(w); + + check_int(buf.len, ==, header_size(1) + footer_size(1)); + + block_source_from_buf(&source, &buf); + + err = reftable_reader_new(&rd, &source, "filename"); + check(!err); + + err = reftable_reader_init_ref_iterator(rd, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, ""); + check(!err); + + err = reftable_iterator_next_ref(&it, &rec); + check_int(err, >, 0); + + reftable_iterator_destroy(&it); + reftable_reader_decref(rd); + reftable_buf_release(&buf); +} + +static void t_write_object_id_min_length(void) +{ + struct reftable_write_options opts = { + .block_size = 75, + }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_ref_record ref = { + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {42}, + }; + int err; + int i; + + reftable_writer_set_limits(w, 1, 1); + + /* Write the same hash in many refs. If there is only 1 hash, the + * disambiguating prefix is length 0 */ + for (i = 0; i < 256; i++) { + char name[256]; + snprintf(name, sizeof(name), "ref%05d", i); + ref.refname = name; + err = reftable_writer_add_ref(w, &ref); + check(!err); + } + + err = reftable_writer_close(w); + check(!err); + check_int(reftable_writer_stats(w)->object_id_len, ==, 2); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_write_object_id_length(void) +{ + struct reftable_write_options opts = { + .block_size = 75, + }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_ref_record ref = { + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {42}, + }; + int err; + int i; + + reftable_writer_set_limits(w, 1, 1); + + /* Write the same hash in many refs. If there is only 1 hash, the + * disambiguating prefix is length 0 */ + for (i = 0; i < 256; i++) { + char name[256]; + snprintf(name, sizeof(name), "ref%05d", i); + ref.refname = name; + ref.value.val1[15] = i; + err = reftable_writer_add_ref(w, &ref); + check(!err); + } + + err = reftable_writer_close(w); + check(!err); + check_int(reftable_writer_stats(w)->object_id_len, ==, 16); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_write_empty_key(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_ref_record ref = { + .refname = (char *) "", + .update_index = 1, + .value_type = REFTABLE_REF_DELETION, + }; + int err; + + reftable_writer_set_limits(w, 1, 1); + err = reftable_writer_add_ref(w, &ref); + check_int(err, ==, REFTABLE_API_ERROR); + + err = reftable_writer_close(w); + check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_write_key_order(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_ref_record refs[2] = { + { + .refname = (char *) "b", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value = { + .symref = (char *) "target", + }, + }, { + .refname = (char *) "a", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value = { + .symref = (char *) "target", + }, + } + }; + int err; + + reftable_writer_set_limits(w, 1, 1); + err = reftable_writer_add_ref(w, &refs[0]); + check(!err); + err = reftable_writer_add_ref(w, &refs[1]); + check_int(err, ==, REFTABLE_API_ERROR); + + refs[0].update_index = 2; + err = reftable_writer_add_ref(w, &refs[0]); + check_int(err, ==, REFTABLE_API_ERROR); + + reftable_writer_close(w); + reftable_writer_free(w); + reftable_buf_release(&buf); +} + +static void t_write_multiple_indices(void) +{ + struct reftable_write_options opts = { + .block_size = 100, + }; + struct reftable_buf writer_buf = REFTABLE_BUF_INIT; + struct reftable_block_source source = { 0 }; + struct reftable_iterator it = { 0 }; + const struct reftable_stats *stats; + struct reftable_writer *writer; + struct reftable_reader *reader; + char buf[128]; + int err, i; + + writer = t_reftable_strbuf_writer(&writer_buf, &opts); + reftable_writer_set_limits(writer, 1, 1); + for (i = 0; i < 100; i++) { + struct reftable_ref_record ref = { + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {i}, + }; + + snprintf(buf, sizeof(buf), "refs/heads/%04d", i); + ref.refname = buf; + + err = reftable_writer_add_ref(writer, &ref); + check(!err); + } + + for (i = 0; i < 100; i++) { + struct reftable_log_record log = { + .update_index = 1, + .value_type = REFTABLE_LOG_UPDATE, + .value.update = { + .old_hash = { i }, + .new_hash = { i }, + }, + }; + + snprintf(buf, sizeof(buf), "refs/heads/%04d", i); + log.refname = buf; + + err = reftable_writer_add_log(writer, &log); + check(!err); + } + + reftable_writer_close(writer); + + /* + * The written data should be sufficiently large to result in indices + * for each of the block types. + */ + stats = reftable_writer_stats(writer); + check_int(stats->ref_stats.index_offset, >, 0); + check_int(stats->obj_stats.index_offset, >, 0); + check_int(stats->log_stats.index_offset, >, 0); + + block_source_from_buf(&source, &writer_buf); + err = reftable_reader_new(&reader, &source, "filename"); + check(!err); + + /* + * Seeking the log uses the log index now. In case there is any + * confusion regarding indices we would notice here. + */ + err = reftable_reader_init_log_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_log(&it, ""); + check(!err); + + reftable_iterator_destroy(&it); + reftable_writer_free(writer); + reftable_reader_decref(reader); + reftable_buf_release(&writer_buf); +} + +static void t_write_multi_level_index(void) +{ + struct reftable_write_options opts = { + .block_size = 100, + }; + struct reftable_buf writer_buf = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_block_source source = { 0 }; + struct reftable_iterator it = { 0 }; + const struct reftable_stats *stats; + struct reftable_writer *writer; + struct reftable_reader *reader; + int err; + + writer = t_reftable_strbuf_writer(&writer_buf, &opts); + reftable_writer_set_limits(writer, 1, 1); + for (size_t i = 0; i < 200; i++) { + struct reftable_ref_record ref = { + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {i}, + }; + char buf[128]; + + snprintf(buf, sizeof(buf), "refs/heads/%03" PRIuMAX, (uintmax_t)i); + ref.refname = buf; + + err = reftable_writer_add_ref(writer, &ref); + check(!err); + } + reftable_writer_close(writer); + + /* + * The written refs should be sufficiently large to result in a + * multi-level index. + */ + stats = reftable_writer_stats(writer); + check_int(stats->ref_stats.max_index_level, ==, 2); + + block_source_from_buf(&source, &writer_buf); + err = reftable_reader_new(&reader, &source, "filename"); + check(!err); + + /* + * Seeking the last ref should work as expected. + */ + err = reftable_reader_init_ref_iterator(reader, &it); + check(!err); + err = reftable_iterator_seek_ref(&it, "refs/heads/199"); + check(!err); + + reftable_iterator_destroy(&it); + reftable_writer_free(writer); + reftable_reader_decref(reader); + reftable_buf_release(&writer_buf); + reftable_buf_release(&buf); +} + +static void t_corrupt_table_empty(void) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_block_source source = { 0 }; + struct reftable_reader *reader; + int err; + + block_source_from_buf(&source, &buf); + err = reftable_reader_new(&reader, &source, "file.log"); + check_int(err, ==, REFTABLE_FORMAT_ERROR); +} + +static void t_corrupt_table(void) +{ + uint8_t zeros[1024] = { 0 }; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct reftable_block_source source = { 0 }; + struct reftable_reader *reader; + int err; + check(!reftable_buf_add(&buf, zeros, sizeof(zeros))); + + block_source_from_buf(&source, &buf); + err = reftable_reader_new(&reader, &source, "file.log"); + check_int(err, ==, REFTABLE_FORMAT_ERROR); + + reftable_buf_release(&buf); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_buffer(), "strbuf works as blocksource"); + TEST(t_corrupt_table(), "read-write on corrupted table"); + TEST(t_corrupt_table_empty(), "read-write on an empty table"); + TEST(t_log_buffer_size(), "buffer extension for log compression"); + TEST(t_log_overflow(), "log overflow returns expected error"); + TEST(t_log_write_read(), "read-write on log records"); + TEST(t_log_zlib_corruption(), "reading corrupted log record returns expected error"); + TEST(t_table_read_api(), "read on a table"); + TEST(t_table_read_write_seek_index(), "read-write on a table with index"); + TEST(t_table_read_write_seek_linear(), "read-write on a table without index (SHA1)"); + TEST(t_table_read_write_seek_linear_sha256(), "read-write on a table without index (SHA256)"); + TEST(t_table_read_write_sequential(), "sequential read-write on a table"); + TEST(t_table_refs_for_no_index(), "refs-only table with no index"); + TEST(t_table_refs_for_obj_index(), "refs-only table with index"); + TEST(t_table_write_small_table(), "write_table works"); + TEST(t_write_empty_key(), "write on refs with empty keys"); + TEST(t_write_empty_table(), "read-write on empty tables"); + TEST(t_write_key_order(), "refs must be written in increasing order"); + TEST(t_write_multi_level_index(), "table with multi-level index"); + TEST(t_write_multiple_indices(), "table with indices for multiple block types"); + TEST(t_write_object_id_length(), "prefix compression on writing refs"); + TEST(t_write_object_id_min_length(), "prefix compression on writing refs"); + + return test_done(); +} diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c index cb649ee419..42bc64cec8 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/t-reftable-record.c @@ -7,6 +7,7 @@ */ #include "test-lib.h" +#include "reftable/basics.h" #include "reftable/constants.h" #include "reftable/record.h" @@ -17,10 +18,10 @@ static void t_copy(struct reftable_record *rec) typ = reftable_record_type(rec); reftable_record_init(©, typ); - reftable_record_copy_from(©, rec, GIT_SHA1_RAWSZ); + reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); /* do it twice to catch memory leaks */ - reftable_record_copy_from(©, rec, GIT_SHA1_RAWSZ); - check(reftable_record_equal(rec, ©, GIT_SHA1_RAWSZ)); + reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); + check(reftable_record_equal(rec, ©, REFTABLE_HASH_SIZE_SHA1)); reftable_record_release(©); } @@ -59,7 +60,7 @@ static void t_varint_roundtrip(void) static void set_hash(uint8_t *h, int j) { - for (int i = 0; i < hash_size(GIT_SHA1_FORMAT_ID); i++) + for (int i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) h[i] = (j >> i) & 0xff; } @@ -84,14 +85,14 @@ static void t_reftable_ref_record_comparison(void) }, }; - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); in[1].u.ref.value_type = in[0].u.ref.value_type; - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); } @@ -116,7 +117,7 @@ static void t_reftable_ref_record_compare_name(void) static void t_reftable_ref_record_roundtrip(void) { - struct strbuf scratch = STRBUF_INIT; + struct reftable_buf scratch = REFTABLE_BUF_INIT; for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) { struct reftable_record in = { @@ -124,7 +125,7 @@ static void t_reftable_ref_record_roundtrip(void) .u.ref.value_type = i, }; struct reftable_record out = { .type = BLOCK_TYPE_REF }; - struct strbuf key = STRBUF_INIT; + struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { .buf = buffer, @@ -155,22 +156,22 @@ static void t_reftable_ref_record_roundtrip(void) check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION); reftable_record_key(&in, &key); - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); check_int(n, >, 0); /* decode into a non-zero reftable_record to test for leaks. */ - m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch); + m = reftable_record_decode(&out, key, i, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); check_int(n, ==, m); check(reftable_ref_record_equal(&in.u.ref, &out.u.ref, - GIT_SHA1_RAWSZ)); + REFTABLE_HASH_SIZE_SHA1)); reftable_record_release(&in); - strbuf_release(&key); + reftable_buf_release(&key); reftable_record_release(&out); } - strbuf_release(&scratch); + reftable_buf_release(&scratch); } static void t_reftable_log_record_comparison(void) @@ -193,15 +194,15 @@ static void t_reftable_log_record_comparison(void) }, }; - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); /* comparison should be reversed for equal keys, because * comparison is now performed on the basis of update indices */ check_int(reftable_record_cmp(&in[0], &in[1]), <, 0); in[1].u.log.update_index = in[0].u.log.update_index; - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); } @@ -262,7 +263,7 @@ static void t_reftable_log_record_roundtrip(void) .value_type = REFTABLE_LOG_UPDATE, } }; - struct strbuf scratch = STRBUF_INIT; + struct reftable_buf scratch = REFTABLE_BUF_INIT; set_hash(in[0].value.update.new_hash, 1); set_hash(in[0].value.update.old_hash, 2); set_hash(in[2].value.update.new_hash, 3); @@ -274,7 +275,7 @@ static void t_reftable_log_record_roundtrip(void) for (size_t i = 0; i < ARRAY_SIZE(in); i++) { struct reftable_record rec = { .type = BLOCK_TYPE_LOG }; - struct strbuf key = STRBUF_INIT; + struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { .buf = buffer, @@ -303,21 +304,21 @@ static void t_reftable_log_record_roundtrip(void) reftable_record_key(&rec, &key); - n = reftable_record_encode(&rec, dest, GIT_SHA1_RAWSZ); + n = reftable_record_encode(&rec, dest, REFTABLE_HASH_SIZE_SHA1); check_int(n, >=, 0); valtype = reftable_record_val_type(&rec); m = reftable_record_decode(&out, key, valtype, dest, - GIT_SHA1_RAWSZ, &scratch); + REFTABLE_HASH_SIZE_SHA1, &scratch); check_int(n, ==, m); check(reftable_log_record_equal(&in[i], &out.u.log, - GIT_SHA1_RAWSZ)); + REFTABLE_HASH_SIZE_SHA1)); reftable_log_record_release(&in[i]); - strbuf_release(&key); + reftable_buf_release(&key); reftable_record_release(&out); } - strbuf_release(&scratch); + reftable_buf_release(&scratch); } static void t_key_roundtrip(void) @@ -327,30 +328,30 @@ static void t_key_roundtrip(void) .buf = buffer, .len = sizeof(buffer), }; - struct strbuf last_key = STRBUF_INIT; - struct strbuf key = STRBUF_INIT; - struct strbuf roundtrip = STRBUF_INIT; + struct reftable_buf last_key = REFTABLE_BUF_INIT; + struct reftable_buf key = REFTABLE_BUF_INIT; + struct reftable_buf roundtrip = REFTABLE_BUF_INIT; int restart; uint8_t extra; int n, m; uint8_t rt_extra; - strbuf_addstr(&last_key, "refs/heads/master"); - strbuf_addstr(&key, "refs/tags/bla"); + check(!reftable_buf_addstr(&last_key, "refs/heads/master")); + check(!reftable_buf_addstr(&key, "refs/tags/bla")); extra = 6; n = reftable_encode_key(&restart, dest, last_key, key, extra); check(!restart); check_int(n, >, 0); - strbuf_addstr(&roundtrip, "refs/heads/master"); + check(!reftable_buf_addstr(&roundtrip, "refs/heads/master")); m = reftable_decode_key(&roundtrip, &rt_extra, dest); check_int(n, ==, m); - check(!strbuf_cmp(&key, &roundtrip)); + check(!reftable_buf_cmp(&key, &roundtrip)); check_int(rt_extra, ==, extra); - strbuf_release(&last_key); - strbuf_release(&key); - strbuf_release(&roundtrip); + reftable_buf_release(&last_key); + reftable_buf_release(&key); + reftable_buf_release(&roundtrip); } static void t_reftable_obj_record_comparison(void) @@ -380,20 +381,20 @@ static void t_reftable_obj_record_comparison(void) }, }; - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); in[1].u.obj.offset_len = in[0].u.obj.offset_len; - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); } static void t_reftable_obj_record_roundtrip(void) { - uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 }; + uint8_t testHash1[REFTABLE_HASH_SIZE_SHA1] = { 1, 2, 3, 4, 0 }; uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; struct reftable_obj_record recs[3] = { { @@ -413,7 +414,7 @@ static void t_reftable_obj_record_roundtrip(void) .hash_prefix_len = 5, }, }; - struct strbuf scratch = STRBUF_INIT; + struct reftable_buf scratch = REFTABLE_BUF_INIT; for (size_t i = 0; i < ARRAY_SIZE(recs); i++) { uint8_t buffer[1024] = { 0 }; @@ -427,7 +428,7 @@ static void t_reftable_obj_record_roundtrip(void) .obj = recs[i], }, }; - struct strbuf key = STRBUF_INIT; + struct reftable_buf key = REFTABLE_BUF_INIT; struct reftable_record out = { .type = BLOCK_TYPE_OBJ }; int n, m; uint8_t extra; @@ -435,19 +436,19 @@ static void t_reftable_obj_record_roundtrip(void) check(!reftable_record_is_deletion(&in)); t_copy(&in); reftable_record_key(&in, &key); - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); check_int(n, >, 0); extra = reftable_record_val_type(&in); m = reftable_record_decode(&out, key, extra, dest, - GIT_SHA1_RAWSZ, &scratch); + REFTABLE_HASH_SIZE_SHA1, &scratch); check_int(n, ==, m); - check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); - strbuf_release(&key); + check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); + reftable_buf_release(&key); reftable_record_release(&out); } - strbuf_release(&scratch); + reftable_buf_release(&scratch); } static void t_reftable_index_record_comparison(void) @@ -456,31 +457,31 @@ static void t_reftable_index_record_comparison(void) { .type = BLOCK_TYPE_INDEX, .u.idx.offset = 22, - .u.idx.last_key = STRBUF_INIT, + .u.idx.last_key = REFTABLE_BUF_INIT, }, { .type = BLOCK_TYPE_INDEX, .u.idx.offset = 32, - .u.idx.last_key = STRBUF_INIT, + .u.idx.last_key = REFTABLE_BUF_INIT, }, { .type = BLOCK_TYPE_INDEX, .u.idx.offset = 32, - .u.idx.last_key = STRBUF_INIT, + .u.idx.last_key = REFTABLE_BUF_INIT, }, }; - strbuf_addstr(&in[0].u.idx.last_key, "refs/heads/master"); - strbuf_addstr(&in[1].u.idx.last_key, "refs/heads/master"); - strbuf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"); + check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master")); + check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); + check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); in[1].u.idx.offset = in[0].u.idx.offset; - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_cmp(&in[0], &in[1])); for (size_t i = 0; i < ARRAY_SIZE(in); i++) @@ -493,7 +494,7 @@ static void t_reftable_index_record_roundtrip(void) .type = BLOCK_TYPE_INDEX, .u.idx = { .offset = 42, - .last_key = STRBUF_INIT, + .last_key = REFTABLE_BUF_INIT, }, }; uint8_t buffer[1024] = { 0 }; @@ -501,38 +502,38 @@ static void t_reftable_index_record_roundtrip(void) .buf = buffer, .len = sizeof(buffer), }; - struct strbuf scratch = STRBUF_INIT; - struct strbuf key = STRBUF_INIT; + struct reftable_buf scratch = REFTABLE_BUF_INIT; + struct reftable_buf key = REFTABLE_BUF_INIT; struct reftable_record out = { .type = BLOCK_TYPE_INDEX, - .u.idx = { .last_key = STRBUF_INIT }, + .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int n, m; uint8_t extra; - strbuf_addstr(&in.u.idx.last_key, "refs/heads/master"); + check(!reftable_buf_addstr(&in.u.idx.last_key, "refs/heads/master")); reftable_record_key(&in, &key); t_copy(&in); check(!reftable_record_is_deletion(&in)); - check(!strbuf_cmp(&key, &in.u.idx.last_key)); - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); + check(!reftable_buf_cmp(&key, &in.u.idx.last_key)); + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); check_int(n, >, 0); extra = reftable_record_val_type(&in); - m = reftable_record_decode(&out, key, extra, dest, GIT_SHA1_RAWSZ, + m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); check_int(m, ==, n); - check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); + check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); reftable_record_release(&out); - strbuf_release(&key); - strbuf_release(&scratch); - strbuf_release(&in.u.idx.last_key); + reftable_buf_release(&key); + reftable_buf_release(&scratch); + reftable_buf_release(&in.u.idx.last_key); } -int cmd_main(int argc, const char *argv[]) +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record"); TEST(t_reftable_log_record_comparison(), "comparison operations work on log record"); diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c new file mode 100644 index 0000000000..b2f6c1c37e --- /dev/null +++ b/t/unit-tests/t-reftable-stack.c @@ -0,0 +1,1397 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "lib-reftable.h" +#include "dir.h" +#include "reftable/merged.h" +#include "reftable/reader.h" +#include "reftable/reftable-error.h" +#include "reftable/stack.h" +#include "strbuf.h" +#include "tempfile.h" +#include <dirent.h> + +static void clear_dir(const char *dirname) +{ + struct strbuf path = REFTABLE_BUF_INIT; + strbuf_addstr(&path, dirname); + remove_dir_recursively(&path, 0); + strbuf_release(&path); +} + +static int count_dir_entries(const char *dirname) +{ + DIR *dir = opendir(dirname); + int len = 0; + struct dirent *d; + if (!dir) + return 0; + + while ((d = readdir(dir))) { + /* + * Besides skipping over "." and "..", we also need to + * skip over other files that have a leading ".". This + * is due to behaviour of NFS, which will rename files + * to ".nfs*" to emulate delete-on-last-close. + * + * In any case this should be fine as the reftable + * library will never write files with leading dots + * anyway. + */ + if (starts_with(d->d_name, ".")) + continue; + len++; + } + closedir(dir); + return len; +} + +/* + * Work linenumber into the tempdir, so we can see which tests forget to + * cleanup. + */ +static char *get_tmp_template(int linenumber) +{ + const char *tmp = getenv("TMPDIR"); + static char template[1024]; + snprintf(template, sizeof(template) - 1, "%s/stack_test-%d.XXXXXX", + tmp ? tmp : "/tmp", linenumber); + return template; +} + +static char *get_tmp_dir(int linenumber) +{ + char *dir = get_tmp_template(linenumber); + check(mkdtemp(dir) != NULL); + return dir; +} + +static void t_read_file(void) +{ + char *fn = get_tmp_template(__LINE__); + struct tempfile *tmp = mks_tempfile(fn); + int fd = get_tempfile_fd(tmp); + char out[1024] = "line1\n\nline2\nline3"; + int n, err; + char **names = NULL; + const char *want[] = { "line1", "line2", "line3" }; + + check_int(fd, >, 0); + n = write_in_full(fd, out, strlen(out)); + check_int(n, ==, strlen(out)); + err = close(fd); + check_int(err, >=, 0); + + err = read_lines(fn, &names); + check(!err); + + for (size_t i = 0; names[i]; i++) + check_str(want[i], names[i]); + free_names(names); + (void) remove(fn); + delete_tempfile(&tmp); +} + +static int write_test_ref(struct reftable_writer *wr, void *arg) +{ + struct reftable_ref_record *ref = arg; + reftable_writer_set_limits(wr, ref->update_index, ref->update_index); + return reftable_writer_add_ref(wr, ref); +} + +static void write_n_ref_tables(struct reftable_stack *st, + size_t n) +{ + int disable_auto_compact; + int err; + + disable_auto_compact = st->opts.disable_auto_compact; + st->opts.disable_auto_compact = 1; + + for (size_t i = 0; i < n; i++) { + struct reftable_ref_record ref = { + .update_index = reftable_stack_next_update_index(st), + .value_type = REFTABLE_REF_VAL1, + }; + char buf[128]; + + snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i); + ref.refname = buf; + t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); + + err = reftable_stack_add(st, &write_test_ref, &ref); + check(!err); + } + + st->opts.disable_auto_compact = disable_auto_compact; +} + +struct write_log_arg { + struct reftable_log_record *log; + uint64_t update_index; +}; + +static int write_test_log(struct reftable_writer *wr, void *arg) +{ + struct write_log_arg *wla = arg; + + reftable_writer_set_limits(wr, wla->update_index, wla->update_index); + return reftable_writer_add_log(wr, wla->log); +} + +static void t_reftable_stack_add_one(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_buf scratch = REFTABLE_BUF_INIT; + int mask = umask(002); + struct reftable_write_options opts = { + .default_permissions = 0660, + }; + struct reftable_stack *st = NULL; + int err; + struct reftable_ref_record ref = { + .refname = (char *) "HEAD", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_ref_record dest = { 0 }; + struct stat stat_result = { 0 }; + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + + err = reftable_stack_read_ref(st, ref.refname, &dest); + check(!err); + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + check_int(st->readers_len, >, 0); + +#ifndef GIT_WINDOWS_NATIVE + check(!reftable_buf_addstr(&scratch, dir)); + check(!reftable_buf_addstr(&scratch, "/tables.list")); + err = stat(scratch.buf, &stat_result); + check(!err); + check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + + reftable_buf_reset(&scratch); + check(!reftable_buf_addstr(&scratch, dir)); + check(!reftable_buf_addstr(&scratch, "/")); + /* do not try at home; not an external API for reftable. */ + check(!reftable_buf_addstr(&scratch, st->readers[0]->name)); + err = stat(scratch.buf, &stat_result); + check(!err); + check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); +#else + (void) stat_result; +#endif + + reftable_ref_record_release(&dest); + reftable_stack_destroy(st); + reftable_buf_release(&scratch); + clear_dir(dir); + umask(mask); +} + +static void t_reftable_stack_uptodate(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st1 = NULL; + struct reftable_stack *st2 = NULL; + char *dir = get_tmp_dir(__LINE__); + + int err; + struct reftable_ref_record ref1 = { + .refname = (char *) "HEAD", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_ref_record ref2 = { + .refname = (char *) "branch2", + .update_index = 2, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + + + /* simulate multi-process access to the same stack + by creating two stacks for the same directory. + */ + err = reftable_new_stack(&st1, dir, &opts); + check(!err); + + err = reftable_new_stack(&st2, dir, &opts); + check(!err); + + err = reftable_stack_add(st1, write_test_ref, &ref1); + check(!err); + + err = reftable_stack_add(st2, write_test_ref, &ref2); + check_int(err, ==, REFTABLE_OUTDATED_ERROR); + + err = reftable_stack_reload(st2); + check(!err); + + err = reftable_stack_add(st2, write_test_ref, &ref2); + check(!err); + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + clear_dir(dir); +} + +static void t_reftable_stack_transaction_api(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err; + struct reftable_addition *add = NULL; + + struct reftable_ref_record ref = { + .refname = (char *) "HEAD", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_ref_record dest = { 0 }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + reftable_addition_destroy(add); + + err = reftable_stack_new_addition(&add, st, 0); + check(!err); + + err = reftable_addition_add(add, write_test_ref, &ref); + check(!err); + + err = reftable_addition_commit(add); + check(!err); + + reftable_addition_destroy(add); + + err = reftable_stack_read_ref(st, ref.refname, &dest); + check(!err); + check_int(REFTABLE_REF_SYMREF, ==, dest.value_type); + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + + reftable_ref_record_release(&dest); + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_transaction_with_reload(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_stack *st1 = NULL, *st2 = NULL; + int err; + struct reftable_addition *add = NULL; + struct reftable_ref_record refs[2] = { + { + .refname = (char *) "refs/heads/a", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { '1' }, + }, + { + .refname = (char *) "refs/heads/b", + .update_index = 2, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { '1' }, + }, + }; + struct reftable_ref_record ref = { 0 }; + + err = reftable_new_stack(&st1, dir, NULL); + check(!err); + err = reftable_new_stack(&st2, dir, NULL); + check(!err); + + err = reftable_stack_new_addition(&add, st1, 0); + check(!err); + err = reftable_addition_add(add, write_test_ref, &refs[0]); + check(!err); + err = reftable_addition_commit(add); + check(!err); + reftable_addition_destroy(add); + + /* + * The second stack is now outdated, which we should notice. We do not + * create the addition and lock the stack by default, but allow the + * reload to happen when REFTABLE_STACK_NEW_ADDITION_RELOAD is set. + */ + err = reftable_stack_new_addition(&add, st2, 0); + check_int(err, ==, REFTABLE_OUTDATED_ERROR); + err = reftable_stack_new_addition(&add, st2, REFTABLE_STACK_NEW_ADDITION_RELOAD); + check(!err); + err = reftable_addition_add(add, write_test_ref, &refs[1]); + check(!err); + err = reftable_addition_commit(add); + check(!err); + reftable_addition_destroy(add); + + for (size_t i = 0; i < ARRAY_SIZE(refs); i++) { + err = reftable_stack_read_ref(st2, refs[i].refname, &ref); + check(!err); + check(reftable_ref_record_equal(&refs[i], &ref, REFTABLE_HASH_SIZE_SHA1)); + } + + reftable_ref_record_release(&ref); + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + clear_dir(dir); +} + +static void t_reftable_stack_transaction_api_performs_auto_compaction(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = {0}; + struct reftable_addition *add = NULL; + struct reftable_stack *st = NULL; + size_t n = 20; + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (size_t i = 0; i <= n; i++) { + struct reftable_ref_record ref = { + .update_index = reftable_stack_next_update_index(st), + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + char name[100]; + + snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); + ref.refname = name; + + /* + * Disable auto-compaction for all but the last runs. Like this + * we can ensure that we indeed honor this setting and have + * better control over when exactly auto compaction runs. + */ + st->opts.disable_auto_compact = i != n; + + err = reftable_stack_new_addition(&add, st, 0); + check(!err); + + err = reftable_addition_add(add, write_test_ref, &ref); + check(!err); + + err = reftable_addition_commit(add); + check(!err); + + reftable_addition_destroy(add); + + /* + * The stack length should grow continuously for all runs where + * auto compaction is disabled. When enabled, we should merge + * all tables in the stack. + */ + if (i != n) + check_int(st->merged->readers_len, ==, i + 1); + else + check_int(st->merged->readers_len, ==, 1); + } + + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_auto_compaction_fails_gracefully(void) +{ + struct reftable_ref_record ref = { + .refname = (char *) "refs/heads/master", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {0x01}, + }; + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st; + struct reftable_buf table_path = REFTABLE_BUF_INIT; + char *dir = get_tmp_dir(__LINE__); + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + check_int(st->merged->readers_len, ==, 1); + check_int(st->stats.attempts, ==, 0); + check_int(st->stats.failures, ==, 0); + + /* + * Lock the newly written table such that it cannot be compacted. + * Adding a new table to the stack should not be impacted by this, even + * though auto-compaction will now fail. + */ + check(!reftable_buf_addstr(&table_path, dir)); + check(!reftable_buf_addstr(&table_path, "/")); + check(!reftable_buf_addstr(&table_path, st->readers[0]->name)); + check(!reftable_buf_addstr(&table_path, ".lock")); + write_file_buf(table_path.buf, "", 0); + + ref.update_index = 2; + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + check_int(st->merged->readers_len, ==, 2); + check_int(st->stats.attempts, ==, 1); + check_int(st->stats.failures, ==, 1); + + reftable_stack_destroy(st); + reftable_buf_release(&table_path); + clear_dir(dir); +} + +static int write_error(struct reftable_writer *wr UNUSED, void *arg) +{ + return *((int *)arg); +} + +static void t_reftable_stack_update_index_check(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err; + struct reftable_ref_record ref1 = { + .refname = (char *) "name1", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_ref_record ref2 = { + .refname = (char *) "name2", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + err = reftable_stack_add(st, write_test_ref, &ref1); + check(!err); + + err = reftable_stack_add(st, write_test_ref, &ref2); + check_int(err, ==, REFTABLE_API_ERROR); + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_lock_failure(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err, i; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) { + err = reftable_stack_add(st, write_error, &i); + check_int(err, ==, i); + } + + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_add(void) +{ + int err = 0; + struct reftable_write_options opts = { + .exact_log_message = 1, + .default_permissions = 0660, + .disable_auto_compact = 1, + }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + struct reftable_ref_record refs[2] = { 0 }; + struct reftable_log_record logs[2] = { 0 }; + struct reftable_buf path = REFTABLE_BUF_INIT; + struct stat stat_result; + size_t i, N = ARRAY_SIZE(refs); + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (i = 0; i < N; i++) { + char buf[256]; + snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); + refs[i].refname = xstrdup(buf); + refs[i].update_index = i + 1; + refs[i].value_type = REFTABLE_REF_VAL1; + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + + logs[i].refname = xstrdup(buf); + logs[i].update_index = N + i + 1; + logs[i].value_type = REFTABLE_LOG_UPDATE; + logs[i].value.update.email = xstrdup("identity@invalid"); + t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + } + + for (i = 0; i < N; i++) { + int err = reftable_stack_add(st, write_test_ref, &refs[i]); + check(!err); + } + + for (i = 0; i < N; i++) { + struct write_log_arg arg = { + .log = &logs[i], + .update_index = reftable_stack_next_update_index(st), + }; + int err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + } + + err = reftable_stack_compact_all(st, NULL); + check(!err); + + for (i = 0; i < N; i++) { + struct reftable_ref_record dest = { 0 }; + + int err = reftable_stack_read_ref(st, refs[i].refname, &dest); + check(!err); + check(reftable_ref_record_equal(&dest, refs + i, + REFTABLE_HASH_SIZE_SHA1)); + reftable_ref_record_release(&dest); + } + + for (i = 0; i < N; i++) { + struct reftable_log_record dest = { 0 }; + int err = reftable_stack_read_log(st, refs[i].refname, &dest); + check(!err); + check(reftable_log_record_equal(&dest, logs + i, + REFTABLE_HASH_SIZE_SHA1)); + reftable_log_record_release(&dest); + } + +#ifndef GIT_WINDOWS_NATIVE + check(!reftable_buf_addstr(&path, dir)); + check(!reftable_buf_addstr(&path, "/tables.list")); + err = stat(path.buf, &stat_result); + check(!err); + check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + + reftable_buf_reset(&path); + check(!reftable_buf_addstr(&path, dir)); + check(!reftable_buf_addstr(&path, "/")); + /* do not try at home; not an external API for reftable. */ + check(!reftable_buf_addstr(&path, st->readers[0]->name)); + err = stat(path.buf, &stat_result); + check(!err); + check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); +#else + (void) stat_result; +#endif + + /* cleanup */ + reftable_stack_destroy(st); + for (i = 0; i < N; i++) { + reftable_ref_record_release(&refs[i]); + reftable_log_record_release(&logs[i]); + } + reftable_buf_release(&path); + clear_dir(dir); +} + +static void t_reftable_stack_iterator(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + struct reftable_ref_record refs[10] = { 0 }; + struct reftable_log_record logs[10] = { 0 }; + struct reftable_iterator it = { 0 }; + size_t N = ARRAY_SIZE(refs), i; + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (i = 0; i < N; i++) { + refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); + refs[i].update_index = i + 1; + refs[i].value_type = REFTABLE_REF_VAL1; + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + + logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); + logs[i].update_index = i + 1; + logs[i].value_type = REFTABLE_LOG_UPDATE; + logs[i].value.update.email = xstrdup("johndoe@invalid"); + logs[i].value.update.message = xstrdup("commit\n"); + t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + } + + for (i = 0; i < N; i++) { + err = reftable_stack_add(st, write_test_ref, &refs[i]); + check(!err); + } + + for (i = 0; i < N; i++) { + struct write_log_arg arg = { + .log = &logs[i], + .update_index = reftable_stack_next_update_index(st), + }; + + err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + } + + reftable_stack_init_ref_iterator(st, &it); + reftable_iterator_seek_ref(&it, refs[0].refname); + for (i = 0; ; i++) { + struct reftable_ref_record ref = { 0 }; + + err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) + break; + check(!err); + check(reftable_ref_record_equal(&ref, &refs[i], REFTABLE_HASH_SIZE_SHA1)); + reftable_ref_record_release(&ref); + } + check_int(i, ==, N); + + reftable_iterator_destroy(&it); + + err = reftable_stack_init_log_iterator(st, &it); + check(!err); + + reftable_iterator_seek_log(&it, logs[0].refname); + for (i = 0; ; i++) { + struct reftable_log_record log = { 0 }; + + err = reftable_iterator_next_log(&it, &log); + if (err > 0) + break; + check(!err); + check(reftable_log_record_equal(&log, &logs[i], REFTABLE_HASH_SIZE_SHA1)); + reftable_log_record_release(&log); + } + check_int(i, ==, N); + + reftable_stack_destroy(st); + reftable_iterator_destroy(&it); + for (i = 0; i < N; i++) { + reftable_ref_record_release(&refs[i]); + reftable_log_record_release(&logs[i]); + } + clear_dir(dir); +} + +static void t_reftable_stack_log_normalize(void) +{ + int err = 0; + struct reftable_write_options opts = { + 0, + }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + struct reftable_log_record input = { + .refname = (char *) "branch", + .update_index = 1, + .value_type = REFTABLE_LOG_UPDATE, + .value = { + .update = { + .new_hash = { 1 }, + .old_hash = { 2 }, + }, + }, + }; + struct reftable_log_record dest = { + .update_index = 0, + }; + struct write_log_arg arg = { + .log = &input, + .update_index = 1, + }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + input.value.update.message = (char *) "one\ntwo"; + err = reftable_stack_add(st, write_test_log, &arg); + check_int(err, ==, REFTABLE_API_ERROR); + + input.value.update.message = (char *) "one"; + err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + + err = reftable_stack_read_log(st, input.refname, &dest); + check(!err); + check_str(dest.value.update.message, "one\n"); + + input.value.update.message = (char *) "two\n"; + arg.update_index = 2; + err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + err = reftable_stack_read_log(st, input.refname, &dest); + check(!err); + check_str(dest.value.update.message, "two\n"); + + /* cleanup */ + reftable_stack_destroy(st); + reftable_log_record_release(&dest); + clear_dir(dir); +} + +static void t_reftable_stack_tombstone(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err; + struct reftable_ref_record refs[2] = { 0 }; + struct reftable_log_record logs[2] = { 0 }; + size_t i, N = ARRAY_SIZE(refs); + struct reftable_ref_record dest = { 0 }; + struct reftable_log_record log_dest = { 0 }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + /* even entries add the refs, odd entries delete them. */ + for (i = 0; i < N; i++) { + const char *buf = "branch"; + refs[i].refname = xstrdup(buf); + refs[i].update_index = i + 1; + if (i % 2 == 0) { + refs[i].value_type = REFTABLE_REF_VAL1; + t_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); + } + + logs[i].refname = xstrdup(buf); + /* update_index is part of the key. */ + logs[i].update_index = 42; + if (i % 2 == 0) { + logs[i].value_type = REFTABLE_LOG_UPDATE; + t_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); + logs[i].value.update.email = + xstrdup("identity@invalid"); + } + } + for (i = 0; i < N; i++) { + int err = reftable_stack_add(st, write_test_ref, &refs[i]); + check(!err); + } + + for (i = 0; i < N; i++) { + struct write_log_arg arg = { + .log = &logs[i], + .update_index = reftable_stack_next_update_index(st), + }; + int err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + } + + err = reftable_stack_read_ref(st, "branch", &dest); + check_int(err, ==, 1); + reftable_ref_record_release(&dest); + + err = reftable_stack_read_log(st, "branch", &log_dest); + check_int(err, ==, 1); + reftable_log_record_release(&log_dest); + + err = reftable_stack_compact_all(st, NULL); + check(!err); + + err = reftable_stack_read_ref(st, "branch", &dest); + check_int(err, ==, 1); + + err = reftable_stack_read_log(st, "branch", &log_dest); + check_int(err, ==, 1); + reftable_ref_record_release(&dest); + reftable_log_record_release(&log_dest); + + /* cleanup */ + reftable_stack_destroy(st); + for (i = 0; i < N; i++) { + reftable_ref_record_release(&refs[i]); + reftable_log_record_release(&logs[i]); + } + clear_dir(dir); +} + +static void t_reftable_stack_hash_id(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err; + + struct reftable_ref_record ref = { + .refname = (char *) "master", + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "target", + .update_index = 1, + }; + struct reftable_write_options opts32 = { .hash_id = REFTABLE_HASH_SHA256 }; + struct reftable_stack *st32 = NULL; + struct reftable_write_options opts_default = { 0 }; + struct reftable_stack *st_default = NULL; + struct reftable_ref_record dest = { 0 }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + + /* can't read it with the wrong hash ID. */ + err = reftable_new_stack(&st32, dir, &opts32); + check_int(err, ==, REFTABLE_FORMAT_ERROR); + + /* check that we can read it back with default opts too. */ + err = reftable_new_stack(&st_default, dir, &opts_default); + check(!err); + + err = reftable_stack_read_ref(st_default, "master", &dest); + check(!err); + + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + reftable_ref_record_release(&dest); + reftable_stack_destroy(st); + reftable_stack_destroy(st_default); + clear_dir(dir); +} + +static void t_suggest_compaction_segment(void) +{ + uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 }; + struct segment min = + suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); + check_int(min.start, ==, 1); + check_int(min.end, ==, 10); +} + +static void t_suggest_compaction_segment_nothing(void) +{ + uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 }; + struct segment result = + suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); + check_int(result.start, ==, result.end); +} + +static void t_reflog_expire(void) +{ + char *dir = get_tmp_dir(__LINE__); + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + struct reftable_log_record logs[20] = { 0 }; + size_t i, N = ARRAY_SIZE(logs) - 1; + int err; + struct reftable_log_expiry_config expiry = { + .time = 10, + }; + struct reftable_log_record log = { 0 }; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (i = 1; i <= N; i++) { + char buf[256]; + snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); + + logs[i].refname = xstrdup(buf); + logs[i].update_index = i; + logs[i].value_type = REFTABLE_LOG_UPDATE; + logs[i].value.update.time = i; + logs[i].value.update.email = xstrdup("identity@invalid"); + t_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); + } + + for (i = 1; i <= N; i++) { + struct write_log_arg arg = { + .log = &logs[i], + .update_index = reftable_stack_next_update_index(st), + }; + int err = reftable_stack_add(st, write_test_log, &arg); + check(!err); + } + + err = reftable_stack_compact_all(st, NULL); + check(!err); + + err = reftable_stack_compact_all(st, &expiry); + check(!err); + + err = reftable_stack_read_log(st, logs[9].refname, &log); + check_int(err, ==, 1); + + err = reftable_stack_read_log(st, logs[11].refname, &log); + check(!err); + + expiry.min_update_index = 15; + err = reftable_stack_compact_all(st, &expiry); + check(!err); + + err = reftable_stack_read_log(st, logs[14].refname, &log); + check_int(err, ==, 1); + + err = reftable_stack_read_log(st, logs[16].refname, &log); + check(!err); + + /* cleanup */ + reftable_stack_destroy(st); + for (i = 0; i <= N; i++) + reftable_log_record_release(&logs[i]); + clear_dir(dir); + reftable_log_record_release(&log); +} + +static int write_nothing(struct reftable_writer *wr, void *arg UNUSED) +{ + reftable_writer_set_limits(wr, 1, 1); + return 0; +} + +static void t_empty_add(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + int err; + char *dir = get_tmp_dir(__LINE__); + struct reftable_stack *st2 = NULL; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + err = reftable_stack_add(st, write_nothing, NULL); + check(!err); + + err = reftable_new_stack(&st2, dir, &opts); + check(!err); + clear_dir(dir); + reftable_stack_destroy(st); + reftable_stack_destroy(st2); +} + +static int fastlogN(uint64_t sz, uint64_t N) +{ + int l = 0; + if (sz == 0) + return 0; + for (; sz; sz /= N) + l++; + return l - 1; +} + +static void t_reftable_stack_auto_compaction(void) +{ + struct reftable_write_options opts = { + .disable_auto_compact = 1, + }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + int err; + size_t i, N = 100; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (i = 0; i < N; i++) { + char name[100]; + struct reftable_ref_record ref = { + .refname = name, + .update_index = reftable_stack_next_update_index(st), + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); + + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + + err = reftable_stack_auto_compact(st); + check(!err); + check(i < 2 || st->merged->readers_len < 2 * fastlogN(i, 2)); + } + + check_int(reftable_stack_compaction_stats(st)->entries_written, <, + (uint64_t)(N * fastlogN(N, 2))); + + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_auto_compaction_factor(void) +{ + struct reftable_write_options opts = { + .auto_compaction_factor = 5, + }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + int err; + size_t N = 100; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (size_t i = 0; i < N; i++) { + char name[20]; + struct reftable_ref_record ref = { + .refname = name, + .update_index = reftable_stack_next_update_index(st), + .value_type = REFTABLE_REF_VAL1, + }; + xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); + + err = reftable_stack_add(st, &write_test_ref, &ref); + check(!err); + + check(i < 5 || st->merged->readers_len < 5 * fastlogN(i, 5)); + } + + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_auto_compaction_with_locked_tables(void) +{ + struct reftable_write_options opts = { + .disable_auto_compact = 1, + }; + struct reftable_stack *st = NULL; + struct reftable_buf buf = REFTABLE_BUF_INIT; + char *dir = get_tmp_dir(__LINE__); + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + write_n_ref_tables(st, 5); + check_int(st->merged->readers_len, ==, 5); + + /* + * Given that all tables we have written should be roughly the same + * size, we expect that auto-compaction will want to compact all of the + * tables. Locking any of the tables will keep it from doing so. + */ + check(!reftable_buf_addstr(&buf, dir)); + check(!reftable_buf_addstr(&buf, "/")); + check(!reftable_buf_addstr(&buf, st->readers[2]->name)); + check(!reftable_buf_addstr(&buf, ".lock")); + write_file_buf(buf.buf, "", 0); + + /* + * When parts of the stack are locked, then auto-compaction does a best + * effort compaction of those tables which aren't locked. So while this + * would in theory compact all tables, due to the preexisting lock we + * only compact the newest two tables. + */ + err = reftable_stack_auto_compact(st); + check(!err); + check_int(st->stats.failures, ==, 0); + check_int(st->merged->readers_len, ==, 4); + + reftable_stack_destroy(st); + reftable_buf_release(&buf); + clear_dir(dir); +} + +static void t_reftable_stack_add_performs_auto_compaction(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + char *dir = get_tmp_dir(__LINE__); + int err; + size_t i, n = 20; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + for (i = 0; i <= n; i++) { + struct reftable_ref_record ref = { + .update_index = reftable_stack_next_update_index(st), + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + char buf[128]; + + /* + * Disable auto-compaction for all but the last runs. Like this + * we can ensure that we indeed honor this setting and have + * better control over when exactly auto compaction runs. + */ + st->opts.disable_auto_compact = i != n; + + snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i); + ref.refname = buf; + + err = reftable_stack_add(st, write_test_ref, &ref); + check(!err); + + /* + * The stack length should grow continuously for all runs where + * auto compaction is disabled. When enabled, we should merge + * all tables in the stack. + */ + if (i != n) + check_int(st->merged->readers_len, ==, i + 1); + else + check_int(st->merged->readers_len, ==, 1); + } + + reftable_stack_destroy(st); + clear_dir(dir); +} + +static void t_reftable_stack_compaction_with_locked_tables(void) +{ + struct reftable_write_options opts = { + .disable_auto_compact = 1, + }; + struct reftable_stack *st = NULL; + struct reftable_buf buf = REFTABLE_BUF_INIT; + char *dir = get_tmp_dir(__LINE__); + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + write_n_ref_tables(st, 3); + check_int(st->merged->readers_len, ==, 3); + + /* Lock one of the tables that we're about to compact. */ + check(!reftable_buf_addstr(&buf, dir)); + check(!reftable_buf_addstr(&buf, "/")); + check(!reftable_buf_addstr(&buf, st->readers[1]->name)); + check(!reftable_buf_addstr(&buf, ".lock")); + write_file_buf(buf.buf, "", 0); + + /* + * Compaction is expected to fail given that we were not able to + * compact all tables. + */ + err = reftable_stack_compact_all(st, NULL); + check_int(err, ==, REFTABLE_LOCK_ERROR); + check_int(st->stats.failures, ==, 1); + check_int(st->merged->readers_len, ==, 3); + + reftable_stack_destroy(st); + reftable_buf_release(&buf); + clear_dir(dir); +} + +static void t_reftable_stack_compaction_concurrent(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st1 = NULL, *st2 = NULL; + char *dir = get_tmp_dir(__LINE__); + int err; + + err = reftable_new_stack(&st1, dir, &opts); + check(!err); + write_n_ref_tables(st1, 3); + + err = reftable_new_stack(&st2, dir, &opts); + check(!err); + + err = reftable_stack_compact_all(st1, NULL); + check(!err); + + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + + check_int(count_dir_entries(dir), ==, 2); + clear_dir(dir); +} + +static void unclean_stack_close(struct reftable_stack *st) +{ + /* break abstraction boundary to simulate unclean shutdown. */ + for (size_t i = 0; i < st->readers_len; i++) + reftable_reader_decref(st->readers[i]); + st->readers_len = 0; + REFTABLE_FREE_AND_NULL(st->readers); +} + +static void t_reftable_stack_compaction_concurrent_clean(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL; + char *dir = get_tmp_dir(__LINE__); + int err; + + err = reftable_new_stack(&st1, dir, &opts); + check(!err); + write_n_ref_tables(st1, 3); + + err = reftable_new_stack(&st2, dir, &opts); + check(!err); + + err = reftable_stack_compact_all(st1, NULL); + check(!err); + + unclean_stack_close(st1); + unclean_stack_close(st2); + + err = reftable_new_stack(&st3, dir, &opts); + check(!err); + + err = reftable_stack_clean(st3); + check(!err); + check_int(count_dir_entries(dir), ==, 2); + + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + reftable_stack_destroy(st3); + + clear_dir(dir); +} + +static void t_reftable_stack_read_across_reload(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st1 = NULL, *st2 = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + char *dir = get_tmp_dir(__LINE__); + int err; + + /* Create a first stack and set up an iterator for it. */ + err = reftable_new_stack(&st1, dir, &opts); + check(!err); + write_n_ref_tables(st1, 2); + check_int(st1->merged->readers_len, ==, 2); + reftable_stack_init_ref_iterator(st1, &it); + err = reftable_iterator_seek_ref(&it, ""); + check(!err); + + /* Set up a second stack for the same directory and compact it. */ + err = reftable_new_stack(&st2, dir, &opts); + check(!err); + check_int(st2->merged->readers_len, ==, 2); + err = reftable_stack_compact_all(st2, NULL); + check(!err); + check_int(st2->merged->readers_len, ==, 1); + + /* + * Verify that we can continue to use the old iterator even after we + * have reloaded its stack. + */ + err = reftable_stack_reload(st1); + check(!err); + check_int(st1->merged->readers_len, ==, 1); + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + check_str(rec.refname, "refs/heads/branch-0000"); + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + check_str(rec.refname, "refs/heads/branch-0001"); + err = reftable_iterator_next_ref(&it, &rec); + check_int(err, >, 0); + + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + clear_dir(dir); +} + +static void t_reftable_stack_reload_with_missing_table(void) +{ + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_buf table_path = REFTABLE_BUF_INIT, content = REFTABLE_BUF_INIT; + char *dir = get_tmp_dir(__LINE__); + int err; + + /* Create a first stack and set up an iterator for it. */ + err = reftable_new_stack(&st, dir, &opts); + check(!err); + write_n_ref_tables(st, 2); + check_int(st->merged->readers_len, ==, 2); + reftable_stack_init_ref_iterator(st, &it); + err = reftable_iterator_seek_ref(&it, ""); + check(!err); + + /* + * Update the tables.list file with some garbage data, while reusing + * our old readers. This should trigger a partial reload of the stack, + * where we try to reuse our old readers. + */ + check(!reftable_buf_addstr(&content, st->readers[0]->name)); + check(!reftable_buf_addstr(&content, "\n")); + check(!reftable_buf_addstr(&content, st->readers[1]->name)); + check(!reftable_buf_addstr(&content, "\n")); + check(!reftable_buf_addstr(&content, "garbage\n")); + check(!reftable_buf_addstr(&table_path, st->list_file)); + check(!reftable_buf_addstr(&table_path, ".lock")); + write_file_buf(table_path.buf, content.buf, content.len); + err = rename(table_path.buf, st->list_file); + check(!err); + + err = reftable_stack_reload(st); + check_int(err, ==, -4); + check_int(st->merged->readers_len, ==, 2); + + /* + * Even though the reload has failed, we should be able to continue + * using the iterator. + */ + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + check_str(rec.refname, "refs/heads/branch-0000"); + err = reftable_iterator_next_ref(&it, &rec); + check(!err); + check_str(rec.refname, "refs/heads/branch-0001"); + err = reftable_iterator_next_ref(&it, &rec); + check_int(err, >, 0); + + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_stack_destroy(st); + reftable_buf_release(&table_path); + reftable_buf_release(&content); + clear_dir(dir); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_empty_add(), "empty addition to stack"); + TEST(t_read_file(), "read_lines works"); + TEST(t_reflog_expire(), "expire reflog entries"); + TEST(t_reftable_stack_add(), "add multiple refs and logs to stack"); + TEST(t_reftable_stack_add_one(), "add a single ref record to stack"); + TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction"); + TEST(t_reftable_stack_auto_compaction(), "stack must form geometric sequence after compaction"); + TEST(t_reftable_stack_auto_compaction_factor(), "auto-compaction with non-default geometric factor"); + TEST(t_reftable_stack_auto_compaction_fails_gracefully(), "failure on auto-compaction"); + TEST(t_reftable_stack_auto_compaction_with_locked_tables(), "auto compaction with locked tables"); + TEST(t_reftable_stack_compaction_concurrent(), "compaction with concurrent stack"); + TEST(t_reftable_stack_compaction_concurrent_clean(), "compaction with unclean stack shutdown"); + TEST(t_reftable_stack_compaction_with_locked_tables(), "compaction with locked tables"); + TEST(t_reftable_stack_hash_id(), "read stack with wrong hash ID"); + TEST(t_reftable_stack_iterator(), "log and ref iterator for reftable stack"); + TEST(t_reftable_stack_lock_failure(), "stack addition with lockfile failure"); + TEST(t_reftable_stack_log_normalize(), "log messages should be normalized"); + TEST(t_reftable_stack_read_across_reload(), "stack iterators work across reloads"); + TEST(t_reftable_stack_reload_with_missing_table(), "stack iteration with garbage tables"); + TEST(t_reftable_stack_tombstone(), "'tombstone' refs in stack"); + TEST(t_reftable_stack_transaction_api(), "update transaction to stack"); + TEST(t_reftable_stack_transaction_with_reload(), "transaction with reload"); + TEST(t_reftable_stack_transaction_api_performs_auto_compaction(), "update transaction triggers auto-compaction"); + TEST(t_reftable_stack_update_index_check(), "update transactions with equal update indices"); + TEST(t_reftable_stack_uptodate(), "stack must be reloaded before ref update"); + TEST(t_suggest_compaction_segment(), "suggest_compaction_segment with basic input"); + TEST(t_suggest_compaction_segment_nothing(), "suggest_compaction_segment with pre-compacted input"); + + return test_done(); +} diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c new file mode 100644 index 0000000000..79b175a45a --- /dev/null +++ b/t/unit-tests/t-reftable-tree.c @@ -0,0 +1,86 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "reftable/tree.h" + +static int t_compare(const void *a, const void *b) +{ + return (char *)a - (char *)b; +} + +struct curry { + void **arr; + size_t len; +}; + +static void store(void *arg, void *key) +{ + struct curry *c = arg; + c->arr[c->len++] = key; +} + +static void t_tree_search(void) +{ + struct tree_node *root = NULL; + void *values[11] = { 0 }; + struct tree_node *nodes[11] = { 0 }; + size_t i = 1; + + /* + * Pseudo-randomly insert the pointers for elements between + * values[1] and values[10] (inclusive) in the tree. + */ + do { + nodes[i] = tree_insert(&root, &values[i], &t_compare); + check(nodes[i] != NULL); + i = (i * 7) % 11; + } while (i != 1); + + for (i = 1; i < ARRAY_SIZE(nodes); i++) { + check_pointer_eq(&values[i], nodes[i]->key); + check_pointer_eq(nodes[i], tree_search(root, &values[i], &t_compare)); + } + + check(!tree_search(root, values, t_compare)); + tree_free(root); +} + +static void t_infix_walk(void) +{ + struct tree_node *root = NULL; + void *values[11] = { 0 }; + void *out[11] = { 0 }; + struct curry c = { + .arr = (void **) &out, + }; + size_t i = 1; + size_t count = 0; + + do { + struct tree_node *node = tree_insert(&root, &values[i], t_compare); + check(node != NULL); + i = (i * 7) % 11; + count++; + } while (i != 1); + + infix_walk(root, &store, &c); + for (i = 1; i < ARRAY_SIZE(values); i++) + check_pointer_eq(&values[i], out[i - 1]); + check(!out[i - 1]); + check_int(c.len, ==, count); + tree_free(root); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_tree_search(), "tree_search works"); + TEST(t_infix_walk(), "infix_walk works"); + + return test_done(); +} diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c index 6027dafef7..3f4044d697 100644 --- a/t/unit-tests/t-strbuf.c +++ b/t/unit-tests/t-strbuf.c @@ -105,7 +105,7 @@ static void t_addstr(struct strbuf *buf, const void *data) check_str(buf->buf + orig_len, text); } -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { if (!TEST(t_static_init(), "static initialization works")) test_skip_all("STRBUF_INIT is broken"); diff --git a/t/unit-tests/t-strcmp-offset.c b/t/unit-tests/t-strcmp-offset.c index fe4c2706b1..6880f21161 100644 --- a/t/unit-tests/t-strcmp-offset.c +++ b/t/unit-tests/t-strcmp-offset.c @@ -24,7 +24,7 @@ static void check_strcmp_offset(const char *string1, const char *string2, expect_offset), \ "strcmp_offset(%s, %s) works", #string1, #string2) -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { TEST_STRCMP_OFFSET("abc", "abc", 0, 3); TEST_STRCMP_OFFSET("abc", "def", -1, 0); diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c deleted file mode 100644 index d4615ab06d..0000000000 --- a/t/unit-tests/t-strvec.c +++ /dev/null @@ -1,272 +0,0 @@ -#include "test-lib.h" -#include "strbuf.h" -#include "strvec.h" - -#define check_strvec(vec, ...) \ - check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__) -LAST_ARG_MUST_BE_NULL -static void check_strvec_loc(const char *loc, struct strvec *vec, ...) -{ - va_list ap; - size_t nr = 0; - - va_start(ap, vec); - while (1) { - const char *str = va_arg(ap, const char *); - if (!str) - break; - - if (!check_uint(vec->nr, >, nr) || - !check_uint(vec->alloc, >, nr) || - !check_str(vec->v[nr], str)) { - struct strbuf msg = STRBUF_INIT; - strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr); - test_assert(loc, msg.buf, 0); - strbuf_release(&msg); - va_end(ap); - return; - } - - nr++; - } - va_end(ap); - - check_uint(vec->nr, ==, nr); - check_uint(vec->alloc, >=, nr); - check_pointer_eq(vec->v[nr], NULL); -} - -static void t_static_init(void) -{ - struct strvec vec = STRVEC_INIT; - check_pointer_eq(vec.v, empty_strvec); - check_uint(vec.nr, ==, 0); - check_uint(vec.alloc, ==, 0); -} - -static void t_dynamic_init(void) -{ - struct strvec vec; - strvec_init(&vec); - check_pointer_eq(vec.v, empty_strvec); - check_uint(vec.nr, ==, 0); - check_uint(vec.alloc, ==, 0); -} - -static void t_clear(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_push(&vec, "foo"); - strvec_clear(&vec); - check_pointer_eq(vec.v, empty_strvec); - check_uint(vec.nr, ==, 0); - check_uint(vec.alloc, ==, 0); -} - -static void t_push(void) -{ - struct strvec vec = STRVEC_INIT; - - strvec_push(&vec, "foo"); - check_strvec(&vec, "foo", NULL); - - strvec_push(&vec, "bar"); - check_strvec(&vec, "foo", "bar", NULL); - - strvec_clear(&vec); -} - -static void t_pushf(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushf(&vec, "foo: %d", 1); - check_strvec(&vec, "foo: 1", NULL); - strvec_clear(&vec); -} - -static void t_pushl(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - check_strvec(&vec, "foo", "bar", "baz", NULL); - strvec_clear(&vec); -} - -static void t_pushv(void) -{ - const char *strings[] = { - "foo", "bar", "baz", NULL, - }; - struct strvec vec = STRVEC_INIT; - - strvec_pushv(&vec, strings); - check_strvec(&vec, "foo", "bar", "baz", NULL); - - strvec_clear(&vec); -} - -static void t_replace_at_head(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_replace(&vec, 0, "replaced"); - check_strvec(&vec, "replaced", "bar", "baz", NULL); - strvec_clear(&vec); -} - -static void t_replace_at_tail(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_replace(&vec, 2, "replaced"); - check_strvec(&vec, "foo", "bar", "replaced", NULL); - strvec_clear(&vec); -} - -static void t_replace_in_between(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_replace(&vec, 1, "replaced"); - check_strvec(&vec, "foo", "replaced", "baz", NULL); - strvec_clear(&vec); -} - -static void t_replace_with_substring(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", NULL); - strvec_replace(&vec, 0, vec.v[0] + 1); - check_strvec(&vec, "oo", NULL); - strvec_clear(&vec); -} - -static void t_remove_at_head(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_remove(&vec, 0); - check_strvec(&vec, "bar", "baz", NULL); - strvec_clear(&vec); -} - -static void t_remove_at_tail(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_remove(&vec, 2); - check_strvec(&vec, "foo", "bar", NULL); - strvec_clear(&vec); -} - -static void t_remove_in_between(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_remove(&vec, 1); - check_strvec(&vec, "foo", "baz", NULL); - strvec_clear(&vec); -} - -static void t_pop_empty_array(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pop(&vec); - check_strvec(&vec, NULL); - strvec_clear(&vec); -} - -static void t_pop_non_empty_array(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_pushl(&vec, "foo", "bar", "baz", NULL); - strvec_pop(&vec); - check_strvec(&vec, "foo", "bar", NULL); - strvec_clear(&vec); -} - -static void t_split_empty_string(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_split(&vec, ""); - check_strvec(&vec, NULL); - strvec_clear(&vec); -} - -static void t_split_single_item(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_split(&vec, "foo"); - check_strvec(&vec, "foo", NULL); - strvec_clear(&vec); -} - -static void t_split_multiple_items(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_split(&vec, "foo bar baz"); - check_strvec(&vec, "foo", "bar", "baz", NULL); - strvec_clear(&vec); -} - -static void t_split_whitespace_only(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_split(&vec, " \t\n"); - check_strvec(&vec, NULL); - strvec_clear(&vec); -} - -static void t_split_multiple_consecutive_whitespaces(void) -{ - struct strvec vec = STRVEC_INIT; - strvec_split(&vec, "foo\n\t bar"); - check_strvec(&vec, "foo", "bar", NULL); - strvec_clear(&vec); -} - -static void t_detach(void) -{ - struct strvec vec = STRVEC_INIT; - const char **detached; - - strvec_push(&vec, "foo"); - - detached = strvec_detach(&vec); - check_str(detached[0], "foo"); - check_pointer_eq(detached[1], NULL); - - check_pointer_eq(vec.v, empty_strvec); - check_uint(vec.nr, ==, 0); - check_uint(vec.alloc, ==, 0); - - free((char *) detached[0]); - free(detached); -} - -int cmd_main(int argc, const char **argv) -{ - TEST(t_static_init(), "static initialization"); - TEST(t_dynamic_init(), "dynamic initialization"); - TEST(t_clear(), "clear"); - TEST(t_push(), "push"); - TEST(t_pushf(), "pushf"); - TEST(t_pushl(), "pushl"); - TEST(t_pushv(), "pushv"); - TEST(t_replace_at_head(), "replace at head"); - TEST(t_replace_in_between(), "replace in between"); - TEST(t_replace_at_tail(), "replace at tail"); - TEST(t_replace_with_substring(), "replace with substring"); - TEST(t_remove_at_head(), "remove at head"); - TEST(t_remove_in_between(), "remove in between"); - TEST(t_remove_at_tail(), "remove at tail"); - TEST(t_pop_empty_array(), "pop with empty array"); - TEST(t_pop_non_empty_array(), "pop with non-empty array"); - TEST(t_split_empty_string(), "split empty string"); - TEST(t_split_single_item(), "split single item"); - TEST(t_split_multiple_items(), "split multiple items"); - TEST(t_split_whitespace_only(), "split whitespace only"); - TEST(t_split_multiple_consecutive_whitespaces(), "split multiple consecutive whitespaces"); - TEST(t_detach(), "detach"); - return test_done(); -} diff --git a/t/unit-tests/t-trailer.c b/t/unit-tests/t-trailer.c index 2ecca359d9..e1c6ad7461 100644 --- a/t/unit-tests/t-trailer.c +++ b/t/unit-tests/t-trailer.c @@ -308,7 +308,7 @@ static void run_t_trailer_iterator(void) } } -int cmd_main(int argc, const char **argv) +int cmd_main(int argc UNUSED, const char **argv UNUSED) { run_t_trailer_iterator(); return test_done(); diff --git a/t/unit-tests/t-urlmatch-normalization.c b/t/unit-tests/t-urlmatch-normalization.c new file mode 100644 index 0000000000..1769c357b9 --- /dev/null +++ b/t/unit-tests/t-urlmatch-normalization.c @@ -0,0 +1,271 @@ +#include "test-lib.h" +#include "urlmatch.h" + +static void check_url_normalizable(const char *url, unsigned int normalizable) +{ + char *url_norm = url_normalize(url, NULL); + + if (!check_int(normalizable, ==, url_norm ? 1 : 0)) + test_msg("input url: %s", url); + free(url_norm); +} + +static void check_normalized_url(const char *url, const char *expect) +{ + char *url_norm = url_normalize(url, NULL); + + if (!check_str(url_norm, expect)) + test_msg("input url: %s", url); + free(url_norm); +} + +static void compare_normalized_urls(const char *url1, const char *url2, + unsigned int equal) +{ + char *url1_norm = url_normalize(url1, NULL); + char *url2_norm = url_normalize(url2, NULL); + + if (equal) { + if (!check_str(url1_norm, url2_norm)) + test_msg("input url1: %s\n input url2: %s", url1, + url2); + } else if (!check_int(strcmp(url1_norm, url2_norm), !=, 0)) { + test_msg(" normalized url1: %s\n normalized url2: %s\n" + " input url1: %s\n input url2: %s", + url1_norm, url2_norm, url1, url2); + } + free(url1_norm); + free(url2_norm); +} + +static void check_normalized_url_length(const char *url, size_t len) +{ + struct url_info info; + char *url_norm = url_normalize(url, &info); + + if (!check_int(info.url_len, ==, len)) + test_msg(" input url: %s\n normalized url: %s", url, + url_norm); + free(url_norm); +} + +/* Note that only "file:" URLs should be allowed without a host */ +static void t_url_scheme(void) +{ + check_url_normalizable("", 0); + check_url_normalizable("_", 0); + check_url_normalizable("scheme", 0); + check_url_normalizable("scheme:", 0); + check_url_normalizable("scheme:/", 0); + check_url_normalizable("scheme://", 0); + check_url_normalizable("file", 0); + check_url_normalizable("file:", 0); + check_url_normalizable("file:/", 0); + check_url_normalizable("file://", 1); + check_url_normalizable("://acme.co", 0); + check_url_normalizable("x_test://acme.co", 0); + check_url_normalizable("-test://acme.co", 0); + check_url_normalizable("0test://acme.co", 0); + check_url_normalizable("+test://acme.co", 0); + check_url_normalizable(".test://acme.co", 0); + check_url_normalizable("schem%6e://", 0); + check_url_normalizable("x-Test+v1.0://acme.co", 1); + check_normalized_url("AbCdeF://x.Y", "abcdef://x.y/"); +} + +static void t_url_authority(void) +{ + check_url_normalizable("scheme://user:pass@", 0); + check_url_normalizable("scheme://?", 0); + check_url_normalizable("scheme://#", 0); + check_url_normalizable("scheme:///", 0); + check_url_normalizable("scheme://:", 0); + check_url_normalizable("scheme://:555", 0); + check_url_normalizable("file://user:pass@", 1); + check_url_normalizable("file://?", 1); + check_url_normalizable("file://#", 1); + check_url_normalizable("file:///", 1); + check_url_normalizable("file://:", 1); + check_url_normalizable("file://:555", 0); + check_url_normalizable("scheme://user:pass@host", 1); + check_url_normalizable("scheme://@host", 1); + check_url_normalizable("scheme://%00@host", 1); + check_url_normalizable("scheme://%%@host", 0); + check_url_normalizable("scheme://host_", 1); + check_url_normalizable("scheme://user:pass@host/", 1); + check_url_normalizable("scheme://@host/", 1); + check_url_normalizable("scheme://host/", 1); + check_url_normalizable("scheme://host?x", 1); + check_url_normalizable("scheme://host#x", 1); + check_url_normalizable("scheme://host/@", 1); + check_url_normalizable("scheme://host?@x", 1); + check_url_normalizable("scheme://host#@x", 1); + check_url_normalizable("scheme://[::1]", 1); + check_url_normalizable("scheme://[::1]/", 1); + check_url_normalizable("scheme://hos%41/", 0); + check_url_normalizable("scheme://[invalid....:/", 1); + check_url_normalizable("scheme://invalid....:]/", 1); + check_url_normalizable("scheme://invalid....:[/", 0); + check_url_normalizable("scheme://invalid....:[", 0); +} + +static void t_url_port(void) +{ + check_url_normalizable("xyz://q@some.host:", 1); + check_url_normalizable("xyz://q@some.host:456/", 1); + check_url_normalizable("xyz://q@some.host:0", 0); + check_url_normalizable("xyz://q@some.host:0000000", 0); + check_url_normalizable("xyz://q@some.host:0000001?", 1); + check_url_normalizable("xyz://q@some.host:065535#", 1); + check_url_normalizable("xyz://q@some.host:65535", 1); + check_url_normalizable("xyz://q@some.host:65536", 0); + check_url_normalizable("xyz://q@some.host:99999", 0); + check_url_normalizable("xyz://q@some.host:100000", 0); + check_url_normalizable("xyz://q@some.host:100001", 0); + check_url_normalizable("http://q@some.host:80", 1); + check_url_normalizable("https://q@some.host:443", 1); + check_url_normalizable("http://q@some.host:80/", 1); + check_url_normalizable("https://q@some.host:443?", 1); + check_url_normalizable("http://q@:8008", 0); + check_url_normalizable("http://:8080", 0); + check_url_normalizable("http://:", 0); + check_url_normalizable("xyz://q@some.host:456/", 1); + check_url_normalizable("xyz://[::1]:456/", 1); + check_url_normalizable("xyz://[::1]:/", 1); + check_url_normalizable("xyz://[::1]:000/", 0); + check_url_normalizable("xyz://[::1]:0%300/", 0); + check_url_normalizable("xyz://[::1]:0x80/", 0); + check_url_normalizable("xyz://[::1]:4294967297/", 0); + check_url_normalizable("xyz://[::1]:030f/", 0); +} + +static void t_url_port_normalization(void) +{ + check_normalized_url("http://x:800", "http://x:800/"); + check_normalized_url("http://x:0800", "http://x:800/"); + check_normalized_url("http://x:00000800", "http://x:800/"); + check_normalized_url("http://x:065535", "http://x:65535/"); + check_normalized_url("http://x:1", "http://x:1/"); + check_normalized_url("http://x:80", "http://x/"); + check_normalized_url("http://x:080", "http://x/"); + check_normalized_url("http://x:000000080", "http://x/"); + check_normalized_url("https://x:443", "https://x/"); + check_normalized_url("https://x:0443", "https://x/"); + check_normalized_url("https://x:000000443", "https://x/"); +} + +static void t_url_general_escape(void) +{ + check_url_normalizable("http://x.y?%fg", 0); + check_normalized_url("X://W/%7e%41^%3a", "x://w/~A%5E%3A"); + check_normalized_url("X://W/:/?#[]@", "x://w/:/?#[]@"); + check_normalized_url("X://W/$&()*+,;=", "x://w/$&()*+,;="); + check_normalized_url("X://W/'", "x://w/'"); + check_normalized_url("X://W?!", "x://w/?!"); +} + +static void t_url_high_bit(void) +{ + check_normalized_url( + "x://q/\x01\x02\x03\x04\x05\x06\x07\x08\x0e\x0f\x10\x11\x12", + "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12"); + check_normalized_url( + "x://q/\x13\x14\x15\x16\x17\x18\x19\x1b\x1c\x1d\x1e\x1f\x7f", + "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F"); + check_normalized_url( + "x://q/\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f", + "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F"); + check_normalized_url( + "x://q/\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", + "x://q/%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F"); + check_normalized_url( + "x://q/\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + "x://q/%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF"); + check_normalized_url( + "x://q/\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", + "x://q/%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF"); + check_normalized_url( + "x://q/\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF"); + check_normalized_url( + "x://q/\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", + "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF"); + check_normalized_url( + "x://q/\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef", + "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF"); + check_normalized_url( + "x://q/\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"); +} + +static void t_url_utf8_escape(void) +{ + check_normalized_url( + "x://q/\xc2\x80\xdf\xbf\xe0\xa0\x80\xef\xbf\xbd\xf0\x90\x80\x80\xf0\xaf\xbf\xbd", + "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"); +} + +static void t_url_username_pass(void) +{ + check_normalized_url("x://%41%62(^):%70+d@foo", "x://Ab(%5E):p+d@foo/"); +} + +static void t_url_length(void) +{ + check_normalized_url_length("Http://%4d%65:%4d^%70@The.Host", 25); + check_normalized_url_length("http://%41:%42@x.y/%61/", 17); + check_normalized_url_length("http://@x.y/^", 15); +} + +static void t_url_dots(void) +{ + check_normalized_url("x://y/.", "x://y/"); + check_normalized_url("x://y/./", "x://y/"); + check_normalized_url("x://y/a/.", "x://y/a"); + check_normalized_url("x://y/a/./", "x://y/a/"); + check_normalized_url("x://y/.?", "x://y/?"); + check_normalized_url("x://y/./?", "x://y/?"); + check_normalized_url("x://y/a/.?", "x://y/a?"); + check_normalized_url("x://y/a/./?", "x://y/a/?"); + check_normalized_url("x://y/a/./b/.././../c", "x://y/c"); + check_normalized_url("x://y/a/./b/../.././c/", "x://y/c/"); + check_normalized_url("x://y/a/./b/.././../c/././.././.", "x://y/"); + check_url_normalizable("x://y/a/./b/.././../c/././.././..", 0); + check_normalized_url("x://y/a/./?/././..", "x://y/a/?/././.."); + check_normalized_url("x://y/%2e/", "x://y/"); + check_normalized_url("x://y/%2E/", "x://y/"); + check_normalized_url("x://y/a/%2e./", "x://y/"); + check_normalized_url("x://y/b/.%2E/", "x://y/"); + check_normalized_url("x://y/c/%2e%2E/", "x://y/"); +} + +/* + * "http://@foo" specifies an empty user name but does not specify a password. + * "http://foo" specifies neither a user name nor a password. + * So they should not be equivalent. + */ +static void t_url_equivalents(void) +{ + compare_normalized_urls("httP://x", "Http://X/", 1); + compare_normalized_urls("Http://%4d%65:%4d^%70@The.Host", "hTTP://Me:%4D^p@the.HOST:80/", 1); + compare_normalized_urls("https://@x.y/^", "httpS://x.y:443/^", 0); + compare_normalized_urls("https://@x.y/^", "httpS://@x.y:0443/^", 1); + compare_normalized_urls("https://@x.y/^/../abc", "httpS://@x.y:0443/abc", 1); + compare_normalized_urls("https://@x.y/^/..", "httpS://@x.y:0443/", 1); +} + +int cmd_main(int argc UNUSED, const char **argv UNUSED) +{ + TEST(t_url_scheme(), "url scheme"); + TEST(t_url_authority(), "url authority"); + TEST(t_url_port(), "url port checks"); + TEST(t_url_port_normalization(), "url port normalization"); + TEST(t_url_general_escape(), "url general escapes"); + TEST(t_url_high_bit(), "url high-bit escapes"); + TEST(t_url_utf8_escape(), "url utf8 escapes"); + TEST(t_url_username_pass(), "url username/password escapes"); + TEST(t_url_length(), "url normalized lengths"); + TEST(t_url_dots(), "url . and .. segments"); + TEST(t_url_equivalents(), "url equivalents"); + return test_done(); +} diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c index 3c513ce59a..fa1f95965c 100644 --- a/t/unit-tests/test-lib.c +++ b/t/unit-tests/test-lib.c @@ -16,6 +16,8 @@ static struct { unsigned running :1; unsigned skip_all :1; unsigned todo :1; + char location[100]; + char description[100]; } ctx = { .lazy_plan = 1, .result = RESULT_NONE, @@ -125,6 +127,8 @@ void test_plan(int count) int test_done(void) { + if (ctx.running && ctx.location[0] && ctx.description[0]) + test__run_end(1, ctx.location, "%s", ctx.description); assert(!ctx.running); if (ctx.lazy_plan) @@ -167,13 +171,38 @@ void test_skip_all(const char *format, ...) va_end(ap); } +void test__run_describe(const char *location, const char *format, ...) +{ + va_list ap; + int len; + + assert(ctx.running); + assert(!ctx.location[0]); + assert(!ctx.description[0]); + + xsnprintf(ctx.location, sizeof(ctx.location), "%s", + make_relative(location)); + + va_start(ap, format); + len = vsnprintf(ctx.description, sizeof(ctx.description), format, ap); + va_end(ap); + if (len < 0) + die("unable to format message: %s", format); + if (len >= sizeof(ctx.description)) + BUG("ctx.description too small to format %s", format); +} + int test__run_begin(void) { + if (ctx.running && ctx.location[0] && ctx.description[0]) + test__run_end(1, ctx.location, "%s", ctx.description); assert(!ctx.running); ctx.count++; ctx.result = RESULT_NONE; ctx.running = 1; + ctx.location[0] = '\0'; + ctx.description[0] = '\0'; return ctx.skip_all; } @@ -264,7 +293,12 @@ static void test_todo(void) int test_assert(const char *location, const char *check, int ok) { - assert(ctx.running); + if (!ctx.running) { + test_msg("BUG: check outside of test at %s", + make_relative(location)); + ctx.failed = 1; + return 0; + } if (ctx.result == RESULT_SKIP) { test_msg("skipping check '%s' at %s", check, diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h index 2de6d715d5..e4b234697f 100644 --- a/t/unit-tests/test-lib.h +++ b/t/unit-tests/test-lib.h @@ -15,6 +15,23 @@ TEST_LOCATION(), __VA_ARGS__) /* + * Run a test unless test_skip_all() has been called. Acts like a + * conditional; the test body is expected as a statement or block after + * the closing parenthesis. The description for each test should be + * unique. E.g.: + * + * if_test ("something else %d %d", arg1, arg2) { + * prepare(); + * test_something_else(arg1, arg2); + * cleanup(); + * } + */ +#define if_test(...) \ + if (test__run_begin() ? \ + (test__run_end(0, TEST_LOCATION(), __VA_ARGS__), 0) : \ + (test__run_describe(TEST_LOCATION(), __VA_ARGS__), 1)) + +/* * Print a test plan, should be called before any tests. If the number * of tests is not known in advance test_done() will automatically * print a plan at the end of the test program. @@ -76,8 +93,9 @@ int test_assert(const char *location, const char *check, int ok); int check_bool_loc(const char *loc, const char *check, int ok); /* - * Compare two integers. Prints a message with the two values if the - * comparison fails. NB this is not thread safe. + * Compare the equality of two pointers of same type. Prints a message + * with the two values if the equality fails. NB this is not thread + * safe. */ #define check_pointer_eq(a, b) \ (test__tmp[0].p = (a), test__tmp[1].p = (b), \ @@ -153,6 +171,9 @@ union test__tmp { extern union test__tmp test__tmp[2]; +__attribute__((format (printf, 2, 3))) +void test__run_describe(const char *, const char *, ...); + int test__run_begin(void); __attribute__((format (printf, 3, 4))) int test__run_end(int, const char *, const char *, ...); diff --git a/t/unit-tests/unit-test.c b/t/unit-tests/unit-test.c new file mode 100644 index 0000000000..a474cdcfd3 --- /dev/null +++ b/t/unit-tests/unit-test.c @@ -0,0 +1,47 @@ +#include "unit-test.h" +#include "parse-options.h" +#include "string-list.h" +#include "strvec.h" + +static const char * const unit_test_usage[] = { + N_("unit-test [<options>]"), + NULL, +}; + +int cmd_main(int argc, const char **argv) +{ + struct string_list run_args = STRING_LIST_INIT_NODUP; + struct string_list exclude_args = STRING_LIST_INIT_NODUP; + int immediate = 0; + struct option options[] = { + OPT_BOOL('i', "immediate", &immediate, + N_("immediately exit upon the first failed test")), + OPT_STRING_LIST('r', "run", &run_args, N_("suite[::test]"), + N_("run only test suite or individual test <suite[::test]>")), + OPT_STRING_LIST('x', "exclude", &exclude_args, N_("suite"), + N_("exclude test suite <suite>")), + OPT_END(), + }; + struct strvec args = STRVEC_INIT; + int ret; + + argc = parse_options(argc, argv, NULL, options, + unit_test_usage, PARSE_OPT_KEEP_ARGV0); + if (argc > 1) + usagef(_("extra command line parameter '%s'"), argv[0]); + + strvec_push(&args, argv[0]); + strvec_push(&args, "-t"); + if (immediate) + strvec_push(&args, "-Q"); + for (size_t i = 0; i < run_args.nr; i++) + strvec_pushf(&args, "-s%s", run_args.items[i].string); + for (size_t i = 0; i < exclude_args.nr; i++) + strvec_pushf(&args, "-x%s", exclude_args.items[i].string); + + ret = clar_test(args.nr, (char **) args.v); + + string_list_clear(&run_args, 0); + strvec_clear(&args); + return ret; +} diff --git a/t/unit-tests/unit-test.h b/t/unit-tests/unit-test.h new file mode 100644 index 0000000000..85e5d6a948 --- /dev/null +++ b/t/unit-tests/unit-test.h @@ -0,0 +1,10 @@ +#include "git-compat-util.h" +#include "clar/clar.h" +#include "clar-decls.h" +#include "strbuf.h" + +#define cl_failf(fmt, ...) do { \ + char desc[4096]; \ + snprintf(desc, sizeof(desc), fmt, __VA_ARGS__); \ + clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1); \ +} while (0) @@ -84,7 +84,7 @@ struct object *deref_tag(struct repository *r, struct object *o, const char *war o = NULL; } if (!o && warn) { - if (last_oid && is_promisor_object(last_oid)) + if (last_oid && is_promisor_object(r, last_oid)) return NULL; if (!warnlen) warnlen = strlen(warn); diff --git a/tmp-objdir.c b/tmp-objdir.c index a8e4553f27..9da0071cba 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -13,6 +13,7 @@ #include "strvec.h" #include "quote.h" #include "object-store-ll.h" +#include "repository.h" struct tmp_objdir { struct strbuf path; @@ -132,7 +133,8 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix) * can recognize any stale objdirs left behind by a crash and delete * them. */ - strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX", get_object_directory(), prefix); + strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX", + repo_get_object_directory(the_repository), prefix); if (!mkdtemp(t->path.buf)) { /* free, not destroy, as we never touched the filesystem */ @@ -152,7 +154,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix) } env_append(&t->env, ALTERNATE_DB_ENVIRONMENT, - absolute_path(get_object_directory())); + absolute_path(repo_get_object_directory(the_repository))); env_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf)); env_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT, absolute_path(t->path.buf)); @@ -204,9 +206,11 @@ 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 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 strbuf *src, struct strbuf *dst, + enum finalize_object_file_flags flags) { struct stat st; @@ -218,12 +222,18 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst) return -1; } else if (errno != EEXIST) return -1; - return migrate_paths(src, dst); + return migrate_paths(src, dst, flags); } - return finalize_object_file(src->buf, dst->buf); + return finalize_object_file_flags(src->buf, dst->buf, flags); } -static int migrate_paths(struct strbuf *src, struct strbuf *dst) +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, + enum finalize_object_file_flags flags) { size_t src_len = src->len, dst_len = dst->len; struct string_list paths = STRING_LIST_INIT_DUP; @@ -237,11 +247,15 @@ static int migrate_paths(struct strbuf *src, struct strbuf *dst) for (i = 0; i < paths.nr; i++) { const char *name = paths.items[i].string; + enum finalize_object_file_flags flags_copy = flags; strbuf_addf(src, "/%s", name); strbuf_addf(dst, "/%s", name); - ret |= migrate_one(src, dst); + if (is_loose_object_shard(name)) + flags_copy |= FOF_SKIP_COLLISION_CHECK; + + ret |= migrate_one(src, dst, flags_copy); strbuf_setlen(src, src_len); strbuf_setlen(dst, dst_len); @@ -267,9 +281,9 @@ int tmp_objdir_migrate(struct tmp_objdir *t) } strbuf_addbuf(&src, &t->path); - strbuf_addstr(&dst, get_object_directory()); + strbuf_addstr(&dst, repo_get_object_directory(the_repository)); - ret = migrate_paths(&src, &dst); + ret = migrate_paths(&src, &dst, 0); strbuf_release(&src); strbuf_release(&dst); @@ -21,9 +21,11 @@ * along with this program; if not, see <https://www.gnu.org/licenses/>. */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" -#include "environment.h" +#include "repository.h" #include "quote.h" #include "setup.h" #include "trace.h" @@ -305,14 +307,14 @@ void trace_repo_setup(void) cwd = xgetcwd(); - if (!(git_work_tree = get_git_work_tree())) + if (!(git_work_tree = repo_get_work_tree(the_repository))) git_work_tree = "(null)"; if (!startup_info->prefix) prefix = "(null)"; - trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(get_git_dir())); - trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(get_git_common_dir())); + trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(repo_get_git_dir(the_repository))); + trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(repo_get_common_dir(the_repository))); trace_printf_key(&trace_setup_key, "setup: worktree: %s\n", quote_crnl(git_work_tree)); trace_printf_key(&trace_setup_key, "setup: cwd: %s\n", quote_crnl(cwd)); trace_printf_key(&trace_setup_key, "setup: prefix: %s\n", quote_crnl(prefix)); @@ -554,6 +554,7 @@ enum trace2_counter_id { TRACE2_COUNTER_ID_TEST2, /* emits summary and thread events */ TRACE2_COUNTER_ID_PACKED_REFS_JUMPS, /* counts number of jumps */ + TRACE2_COUNTER_ID_REFTABLE_RESEEKS, /* counts number of re-seeks */ /* counts number of fsyncs */ TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY, diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c index d96d908bb9..22a99a0682 100644 --- a/trace2/tr2_cfg.c +++ b/trace2/tr2_cfg.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "strbuf.h" @@ -124,7 +126,7 @@ void tr2_cfg_list_config_fl(const char *file, int line) struct tr2_cfg_data data = { file, line }; if (tr2_cfg_load_patterns() > 0) - read_early_config(tr2_cfg_cb, &data); + read_early_config(the_repository, tr2_cfg_cb, &data); } void tr2_list_env_vars_fl(const char *file, int line) diff --git a/trace2/tr2_ctr.c b/trace2/tr2_ctr.c index d3a33715c1..ee17bfa86b 100644 --- a/trace2/tr2_ctr.c +++ b/trace2/tr2_ctr.c @@ -4,7 +4,7 @@ #include "trace2/tr2_ctr.h" /* - * A global counter block to aggregrate values from the partial sums + * A global counter block to aggregate values from the partial sums * from each thread. */ static struct tr2_counter_block final_counter_block; /* access under tr2tls_mutex */ @@ -31,6 +31,11 @@ static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTER .name = "jumps_made", .want_per_thread_events = 0, }, + [TRACE2_COUNTER_ID_REFTABLE_RESEEKS] = { + .category = "reftable", + .name = "reseeks_made", + .want_per_thread_events = 0, + }, [TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY] = { .category = "fsync", .name = "writeout-only", diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c index 59910a1a4f..45b0850a5e 100644 --- a/trace2/tr2_tgt_event.c +++ b/trace2/tr2_tgt_event.c @@ -24,7 +24,7 @@ static struct tr2_dst tr2dst_event = { * a new field to an existing event, do not require an increment to the EVENT * format version. */ -#define TR2_EVENT_VERSION "3" +#define TR2_EVENT_VERSION "4" /* * Region nesting limit for messages written to the event target. @@ -622,6 +622,24 @@ static void fn_data_json_fl(const char *file, int line, } } +static void fn_printf_va_fl(const char *file, int line, + uint64_t us_elapsed_absolute, + const char *fmt, va_list ap) +{ + const char *event_name = "printf"; + struct json_writer jw = JSON_WRITER_INIT; + double t_abs = (double)us_elapsed_absolute / 1000000.0; + + jw_object_begin(&jw, 0); + event_fmt_prepare(event_name, file, line, NULL, &jw); + jw_object_double(&jw, "t_abs", 6, t_abs); + maybe_add_string_va(&jw, "msg", fmt, ap); + jw_end(&jw); + + tr2_dst_write_line(&tr2dst_event, &jw.json); + jw_release(&jw); +} + static void fn_timer(const struct tr2_timer_metadata *meta, const struct tr2_timer *timer, int is_final_data) @@ -694,7 +712,7 @@ struct tr2_tgt tr2_tgt_event = { .pfn_region_leave_printf_va_fl = fn_region_leave_printf_va_fl, .pfn_data_fl = fn_data_fl, .pfn_data_json_fl = fn_data_json_fl, - .pfn_printf_va_fl = NULL, + .pfn_printf_va_fl = fn_printf_va_fl, .pfn_timer = fn_timer, .pfn_counter = fn_counter, }; diff --git a/trace2/tr2_tls.c b/trace2/tr2_tls.c index 4f75392952..7b023c1bfc 100644 --- a/trace2/tr2_tls.c +++ b/trace2/tr2_tls.c @@ -152,11 +152,19 @@ uint64_t tr2tls_absolute_elapsed(uint64_t us) return us - tr2tls_us_start_process; } +static void tr2tls_key_destructor(void *payload) +{ + struct tr2tls_thread_ctx *ctx = payload; + free((char *)ctx->thread_name); + free(ctx->array_us_start); + free(ctx); +} + void tr2tls_init(void) { tr2tls_start_process_clock(); - pthread_key_create(&tr2tls_key, NULL); + pthread_key_create(&tr2tls_key, tr2tls_key_destructor); init_recursive_mutex(&tr2tls_mutex); tr2tls_thread_main = diff --git a/trace2/tr2_tls.h b/trace2/tr2_tls.h index 3dfe6557fc..3bdbf4d275 100644 --- a/trace2/tr2_tls.h +++ b/trace2/tr2_tls.h @@ -11,7 +11,7 @@ */ /* - * Arbitry limit for thread names for column alignment. + * Arbitrary limit for thread names for column alignment. */ #define TR2_MAX_THREAD_NAME (24) @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "environment.h" @@ -11,19 +13,20 @@ * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org> */ -struct trailer_info { +struct trailer_block { /* * True if there is a blank line before the location pointed to by - * trailer_block_start. + * "start". */ int blank_line_before_trailer; /* - * Offsets to the trailer block start and end positions in the input - * string. If no trailer block is found, these are both set to the - * "true" end of the input (find_end_of_log_message()). + * The locations of the start and end positions of the trailer block + * found, as offsets from the beginning of the source text from which + * this trailer block was parsed. If no trailer block is found, these + * are both set to 0. */ - size_t trailer_block_start, trailer_block_end; + size_t start, end; /* * Array of trailers found. @@ -247,7 +250,9 @@ static char *apply_command(struct conf_info *conf, const char *arg) static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok) { if (arg_tok->conf.command || arg_tok->conf.cmd) { - const char *arg; + char *value_to_free = NULL; + char *arg; + if (arg_tok->value && arg_tok->value[0]) { arg = arg_tok->value; } else { @@ -255,9 +260,13 @@ static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg arg = xstrdup(in_tok->value); else arg = xstrdup(""); + value_to_free = arg_tok->value; } + arg_tok->value = apply_command(&arg_tok->conf, arg); - free((char *)arg); + + free(value_to_free); + free(arg); } } @@ -973,16 +982,16 @@ static void unfold_value(struct strbuf *val) strbuf_release(&out); } -static struct trailer_info *trailer_info_new(void) +static struct trailer_block *trailer_block_new(void) { - struct trailer_info *info = xcalloc(1, sizeof(*info)); - return info; + struct trailer_block *trailer_block = xcalloc(1, sizeof(*trailer_block)); + return trailer_block; } -static struct trailer_info *trailer_info_get(const struct process_trailer_options *opts, - const char *str) +static struct trailer_block *trailer_block_get(const struct process_trailer_options *opts, + const char *str) { - struct trailer_info *info = trailer_info_new(); + struct trailer_block *trailer_block = trailer_block_new(); size_t end_of_log_message = 0, trailer_block_start = 0; struct strbuf **trailer_lines, **ptr; char **trailer_strings = NULL; @@ -1015,34 +1024,34 @@ static struct trailer_info *trailer_info_get(const struct process_trailer_option } strbuf_list_free(trailer_lines); - info->blank_line_before_trailer = ends_with_blank_line(str, - trailer_block_start); - info->trailer_block_start = trailer_block_start; - info->trailer_block_end = end_of_log_message; - info->trailers = trailer_strings; - info->trailer_nr = nr; + trailer_block->blank_line_before_trailer = ends_with_blank_line(str, + trailer_block_start); + trailer_block->start = trailer_block_start; + trailer_block->end = end_of_log_message; + trailer_block->trailers = trailer_strings; + trailer_block->trailer_nr = nr; - return info; + return trailer_block; } /* - * Parse trailers in "str", populating the trailer info and "trailer_objects" + * Parse trailers in "str", populating the trailer_block and "trailer_objects" * linked list structure. */ -struct trailer_info *parse_trailers(const struct process_trailer_options *opts, - const char *str, - struct list_head *trailer_objects) +struct trailer_block *parse_trailers(const struct process_trailer_options *opts, + const char *str, + struct list_head *trailer_objects) { - struct trailer_info *info; + struct trailer_block *trailer_block; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; size_t i; - info = trailer_info_get(opts, str); + trailer_block = trailer_block_get(opts, str); - for (i = 0; i < info->trailer_nr; i++) { + for (i = 0; i < trailer_block->trailer_nr; i++) { int separator_pos; - char *trailer = info->trailers[i]; + char *trailer = trailer_block->trailers[i]; if (starts_with(trailer, comment_line_str)) continue; separator_pos = find_separator(trailer, separators); @@ -1063,7 +1072,7 @@ struct trailer_info *parse_trailers(const struct process_trailer_options *opts, } } - return info; + return trailer_block; } void free_trailers(struct list_head *trailers) @@ -1075,34 +1084,36 @@ void free_trailers(struct list_head *trailers) } } -size_t trailer_block_start(struct trailer_info *info) +size_t trailer_block_start(struct trailer_block *trailer_block) { - return info->trailer_block_start; + return trailer_block->start; } -size_t trailer_block_end(struct trailer_info *info) +size_t trailer_block_end(struct trailer_block *trailer_block) { - return info->trailer_block_end; + return trailer_block->end; } -int blank_line_before_trailer_block(struct trailer_info *info) +int blank_line_before_trailer_block(struct trailer_block *trailer_block) { - return info->blank_line_before_trailer; + return trailer_block->blank_line_before_trailer; } -void trailer_info_release(struct trailer_info *info) +void trailer_block_release(struct trailer_block *trailer_block) { size_t i; - for (i = 0; i < info->trailer_nr; i++) - free(info->trailers[i]); - free(info->trailers); - free(info); + for (i = 0; i < trailer_block->trailer_nr; i++) + free(trailer_block->trailers[i]); + free(trailer_block->trailers); + free(trailer_block); } void format_trailers(const struct process_trailer_options *opts, struct list_head *trailers, struct strbuf *out) { + struct strbuf tok = STRBUF_INIT; + struct strbuf val = STRBUF_INIT; size_t origlen = out->len; struct list_head *pos; struct trailer_item *item; @@ -1110,9 +1121,9 @@ void format_trailers(const struct process_trailer_options *opts, list_for_each(pos, trailers) { item = list_entry(pos, struct trailer_item, list); if (item->token) { - struct strbuf tok = STRBUF_INIT; - struct strbuf val = STRBUF_INIT; + strbuf_reset(&tok); strbuf_addstr(&tok, item->token); + strbuf_reset(&val); strbuf_addstr(&val, item->value); /* @@ -1143,9 +1154,6 @@ void format_trailers(const struct process_trailer_options *opts, if (!opts->separator) strbuf_addch(out, '\n'); } - strbuf_release(&tok); - strbuf_release(&val); - } else if (!opts->only_trailers) { if (opts->separator && out->len != origlen) { strbuf_addbuf(out, opts->separator); @@ -1157,6 +1165,9 @@ void format_trailers(const struct process_trailer_options *opts, strbuf_addch(out, '\n'); } } + + strbuf_release(&tok); + strbuf_release(&val); } void format_trailers_from_commit(const struct process_trailer_options *opts, @@ -1164,19 +1175,19 @@ void format_trailers_from_commit(const struct process_trailer_options *opts, struct strbuf *out) { LIST_HEAD(trailer_objects); - struct trailer_info *info = parse_trailers(opts, msg, &trailer_objects); + struct trailer_block *trailer_block = parse_trailers(opts, msg, &trailer_objects); /* If we want the whole block untouched, we can take the fast path. */ if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator && !opts->key_only && !opts->value_only && !opts->key_value_separator) { - strbuf_add(out, msg + info->trailer_block_start, - info->trailer_block_end - info->trailer_block_start); + strbuf_add(out, msg + trailer_block->start, + trailer_block->end - trailer_block->start); } else format_trailers(opts, &trailer_objects, out); free_trailers(&trailer_objects); - trailer_info_release(info); + trailer_block_release(trailer_block); } void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) @@ -1185,14 +1196,14 @@ void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) strbuf_init(&iter->key, 0); strbuf_init(&iter->val, 0); opts.no_divider = 1; - iter->internal.info = trailer_info_get(&opts, msg); + iter->internal.trailer_block = trailer_block_get(&opts, msg); iter->internal.cur = 0; } int trailer_iterator_advance(struct trailer_iterator *iter) { - if (iter->internal.cur < iter->internal.info->trailer_nr) { - char *line = iter->internal.info->trailers[iter->internal.cur++]; + if (iter->internal.cur < iter->internal.trailer_block->trailer_nr) { + char *line = iter->internal.trailer_block->trailers[iter->internal.cur++]; int separator_pos = find_separator(line, separators); iter->raw = line; @@ -1209,7 +1220,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) void trailer_iterator_release(struct trailer_iterator *iter) { - trailer_info_release(iter->internal.info); + trailer_block_release(iter->internal.trailer_block); strbuf_release(&iter->val); strbuf_release(&iter->key); } @@ -4,7 +4,7 @@ #include "list.h" #include "strbuf.h" -struct trailer_info; +struct trailer_block; struct strvec; enum trailer_where { @@ -72,12 +72,12 @@ void process_trailers_lists(struct list_head *head, struct list_head *arg_head); /* - * Given some input string "str", return a pointer to an opaque trailer_info + * Given some input string "str", return a pointer to an opaque trailer_block * structure. Also populate the trailer_objects list with parsed trailer * objects. Internally this calls trailer_info_get() to get the opaque pointer, * but does some extra work to populate the trailer_objects linked list. * - * The opaque trailer_info pointer can be used to check the position of the + * The opaque trailer_block pointer can be used to check the position of the * trailer block as offsets relative to the beginning of "str" in * trailer_block_start() and trailer_block_end(). * blank_line_before_trailer_block() returns 1 if there is a blank line just @@ -89,21 +89,21 @@ void process_trailers_lists(struct list_head *head, * For iterating through the parsed trailer block (if you don't care about the * position of the trailer block itself in the context of the larger string text * from which it was parsed), please see trailer_iterator_init() which uses the - * trailer_info struct internally. + * trailer_block struct internally. * * Lastly, callers should call trailer_info_release() when they are done using * the opaque pointer. * - * NOTE: Callers should treat both trailer_info and trailer_objects as - * read-only items, because there is some overlap between the two (trailer_info + * NOTE: Callers should treat both trailer_block and trailer_objects as + * read-only items, because there is some overlap between the two (trailer_block * has "char **trailers" string array, and trailer_objects will have the same * data but as a linked list of trailer_item objects). This API does not perform * any synchronization between the two. In the future we should be able to * reduce the duplication and use just the linked list. */ -struct trailer_info *parse_trailers(const struct process_trailer_options *, - const char *str, - struct list_head *trailer_objects); +struct trailer_block *parse_trailers(const struct process_trailer_options *, + const char *str, + struct list_head *trailer_objects); /* * Return the offset of the start of the trailer block. That is, 0 is the start @@ -111,24 +111,24 @@ struct trailer_info *parse_trailers(const struct process_trailer_options *, * indicates how many bytes we have to skip over before we get to the beginning * of the trailer block. */ -size_t trailer_block_start(struct trailer_info *); +size_t trailer_block_start(struct trailer_block *); /* * Return the end of the trailer block, again relative to the start of the * input. */ -size_t trailer_block_end(struct trailer_info *); +size_t trailer_block_end(struct trailer_block *); /* * Return 1 if the trailer block had an extra newline (blank line) just before * it. */ -int blank_line_before_trailer_block(struct trailer_info *); +int blank_line_before_trailer_block(struct trailer_block *); /* - * Free trailer_info struct. + * Free trailer_block struct. */ -void trailer_info_release(struct trailer_info *info); +void trailer_block_release(struct trailer_block *); void trailer_config_init(void); void format_trailers(const struct process_trailer_options *, @@ -167,7 +167,7 @@ struct trailer_iterator { /* private */ struct { - struct trailer_info *info; + struct trailer_block *trailer_block; size_t cur; } internal; }; diff --git a/transport-helper.c b/transport-helper.c index 09b3560ffd..bc27653cde 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -89,11 +89,18 @@ static int recvline(struct helper_data *helper, struct strbuf *buffer) return recvline_fh(helper->out, buffer); } -static void write_constant(int fd, const char *str) +static int write_constant_gently(int fd, const char *str) { if (debug) fprintf(stderr, "Debug: Remote helper: -> %s", str); if (write_in_full(fd, str, strlen(str)) < 0) + return -1; + return 0; +} + +static void write_constant(int fd, const char *str) +{ + if (write_constant_gently(fd, str) < 0) die_errno(_("full write to remote helper failed")); } @@ -143,7 +150,7 @@ static struct child_process *get_helper(struct transport *transport) if (have_git_dir()) strvec_pushf(&helper->env, "%s=%s", - GIT_DIR_ENVIRONMENT, get_git_dir()); + GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository)); helper->trace2_child_class = helper->args.v[0]; /* "remote-<name>" */ @@ -168,13 +175,16 @@ static struct child_process *get_helper(struct transport *transport) die_errno(_("can't dup helper output fd")); data->out = xfdopen(duped, "r"); - write_constant(helper->in, "capabilities\n"); + sigchain_push(SIGPIPE, SIG_IGN); + if (write_constant_gently(helper->in, "capabilities\n") < 0) + die("remote helper '%s' aborted session", data->name); + sigchain_pop(SIGPIPE); while (1) { const char *capname, *arg; int mandatory = 0; if (recvline(data, &buf)) - exit(128); + die("remote helper '%s' aborted session", data->name); if (!*buf.buf) break; @@ -389,6 +399,8 @@ static int release_helper(struct transport *transport) int res = 0; struct helper_data *data = transport->data; refspec_clear(&data->rs); + free(data->import_marks); + free(data->export_marks); res = disconnect_helper(transport); free(transport->data); return res; @@ -707,8 +719,14 @@ static int fetch_refs(struct transport *transport, return -1; } - if (!data->get_refs_list_called) - get_refs_list_using_list(transport, 0); + if (!data->get_refs_list_called) { + /* + * We do not care about the list of refs returned, but only + * that the "list" command was sent. + */ + struct ref *dummy = get_refs_list_using_list(transport, 0); + free_refs(dummy); + } count = 0; for (i = 0; i < nr_heads; i++) @@ -1013,6 +1031,7 @@ static int push_refs_with_push(struct transport *transport, if (atomic) { reject_atomic_push(remote_refs, mirror); string_list_clear(&cas_options, 0); + strbuf_release(&buf); return 0; } else continue; diff --git a/transport.c b/transport.c index 12cc5b4d96..6966df51a8 100644 --- a/transport.c +++ b/transport.c @@ -19,6 +19,7 @@ #include "branch.h" #include "url.h" #include "submodule.h" +#include "strbuf.h" #include "string-list.h" #include "oid-array.h" #include "sigchain.h" @@ -172,12 +173,29 @@ static struct ref *get_refs_from_bundle(struct transport *transport, return result; } +static int fetch_fsck_config_cb(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *cb) +{ + struct strbuf *msg_types = cb; + int ret; + + ret = fetch_pack_fsck_config(var, value, msg_types); + if (ret > 0) + return 0; + + return ret; +} + static int fetch_refs_from_bundle(struct transport *transport, int nr_heads UNUSED, struct ref **to_fetch UNUSED) { + struct unbundle_opts opts = { + .flags = fetch_pack_fsck_objects() ? VERIFY_BUNDLE_FSCK : 0, + }; struct bundle_transport_data *data = transport->data; struct strvec extra_index_pack_args = STRVEC_INIT; + struct strbuf msg_types = STRBUF_INIT; int ret; if (transport->progress) @@ -185,10 +203,16 @@ static int fetch_refs_from_bundle(struct transport *transport, if (!data->get_refs_from_bundle_called) get_refs_from_bundle_inner(transport); + + git_config(fetch_fsck_config_cb, &msg_types); + opts.fsck_msg_types = msg_types.buf; + ret = unbundle(the_repository, &data->header, data->fd, - &extra_index_pack_args, - fetch_pack_fsck_objects() ? VERIFY_BUNDLE_FSCK : 0); + &extra_index_pack_args, &opts); transport->hash_algo = data->header.hash_algo; + + strvec_clear(&extra_index_pack_args); + strbuf_release(&msg_types); return ret; } @@ -332,6 +356,9 @@ static struct ref *handshake(struct transport *transport, int for_push, data->version = discover_version(&reader); switch (data->version) { case protocol_v2: + if ((!transport->server_options || !transport->server_options->nr) && + transport->remote->server_options.nr) + transport->server_options = &transport->remote->server_options; if (server_feature_v2("session-id", &server_sid)) trace2_data_string("transfer", NULL, "server-sid", server_sid); if (must_list_refs) @@ -412,7 +439,7 @@ static int fetch_refs_via_pack(struct transport *transport, struct git_transport_data *data = transport->data; struct ref *refs = NULL; struct fetch_pack_args args; - struct ref *refs_tmp = NULL; + struct ref *refs_tmp = NULL, **to_fetch_dup = NULL; memset(&args, 0, sizeof(args)); args.uploadpack = data->options.uploadpack; @@ -475,6 +502,14 @@ static int fetch_refs_via_pack(struct transport *transport, goto cleanup; } + /* + * Create a shallow copy of `sought` so that we can free all of its entries. + * This is because `fetch_pack()` will modify the array to evict some + * entries, but won't free those. + */ + DUP_ARRAY(to_fetch_dup, to_fetch, nr_heads); + to_fetch = to_fetch_dup; + refs = fetch_pack(&args, data->fd, refs_tmp ? refs_tmp : transport->remote_refs, to_fetch, nr_heads, &data->shallow, @@ -498,6 +533,7 @@ cleanup: ret = -1; data->conn = NULL; + free(to_fetch_dup); free_refs(refs_tmp); free_refs(refs); list_objects_filter_release(&args.filter_options); @@ -945,7 +981,13 @@ static int disconnect_git(struct transport *transport) finish_connect(data->conn); } + if (data->options.negotiation_tips) { + oid_array_clear(data->options.negotiation_tips); + free(data->options.negotiation_tips); + } list_objects_filter_release(&data->options.filter_options); + oid_array_clear(&data->extra_have); + oid_array_clear(&data->shallow); free(data); return 0; } @@ -1091,6 +1133,18 @@ int is_transport_allowed(const char *type, int from_user) BUG("invalid protocol_allow_config type"); } +int parse_transport_option(const char *var, const char *value, + struct string_list *transport_options) +{ + if (!value) + return config_error_nonbool(var); + if (!*value) + string_list_clear(transport_options, 0); + else + string_list_append(transport_options, value); + return 0; +} + void transport_check_allowed(const char *type) { if (!is_transport_allowed(type, -1)) @@ -1115,6 +1169,7 @@ static struct transport_vtable builtin_smart_vtable = { struct transport *transport_get(struct remote *remote, const char *url) { const char *helper; + char *helper_to_free = NULL; const char *p; struct transport *ret = xcalloc(1, sizeof(*ret)); @@ -1139,10 +1194,11 @@ struct transport *transport_get(struct remote *remote, const char *url) while (is_urlschemechar(p == url, *p)) p++; if (starts_with(p, "::")) - helper = xstrndup(url, p - url); + helper = helper_to_free = xstrndup(url, p - url); if (helper) { transport_helper_init(ret, helper); + free(helper_to_free); } else if (starts_with(url, "rsync:")) { die(_("git-over-rsync is no longer supported")); } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) { @@ -1271,7 +1327,7 @@ static int run_pre_push_hook(struct transport *transport, struct ref *r; struct child_process proc = CHILD_PROCESS_INIT; struct strbuf buf; - const char *hook_path = find_hook("pre-push"); + const char *hook_path = find_hook(the_repository, "pre-push"); if (!hook_path) return 0; diff --git a/transport.h b/transport.h index 6393cd9823..44100fa9b7 100644 --- a/transport.h +++ b/transport.h @@ -342,4 +342,8 @@ void transport_print_push_status(const char *dest, struct ref *refs, /* common method used by transport-helper.c and send-pack.c */ void reject_atomic_push(struct ref *refs, int mirror_mode); +/* common method to parse push-option or server-option from config */ +int parse_transport_option(const char *var, const char *value, + struct string_list *transport_options); + #endif diff --git a/tree-diff.c b/tree-diff.c index 9252481df3..5eab8af631 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -1,6 +1,9 @@ /* * Helper functions for tree diff generation */ + +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "diff.h" #include "diffcore.h" diff --git a/unicode-width.h b/unicode-width.h index be5bf8c4f2..3ffee123a0 100644 --- a/unicode-width.h +++ b/unicode-width.h @@ -27,7 +27,7 @@ static const struct interval zero_width[] = { { 0x0829, 0x082D }, { 0x0859, 0x085B }, { 0x0890, 0x0891 }, -{ 0x0898, 0x089F }, +{ 0x0897, 0x089F }, { 0x08CA, 0x0902 }, { 0x093A, 0x093A }, { 0x093C, 0x093C }, @@ -227,8 +227,9 @@ static const struct interval zero_width[] = { { 0x10A3F, 0x10A3F }, { 0x10AE5, 0x10AE6 }, { 0x10D24, 0x10D27 }, +{ 0x10D69, 0x10D6D }, { 0x10EAB, 0x10EAC }, -{ 0x10EFD, 0x10EFF }, +{ 0x10EFC, 0x10EFF }, { 0x10F46, 0x10F50 }, { 0x10F82, 0x10F85 }, { 0x11001, 0x11001 }, @@ -261,6 +262,11 @@ static const struct interval zero_width[] = { { 0x11340, 0x11340 }, { 0x11366, 0x1136C }, { 0x11370, 0x11374 }, +{ 0x113BB, 0x113C0 }, +{ 0x113CE, 0x113CE }, +{ 0x113D0, 0x113D0 }, +{ 0x113D2, 0x113D2 }, +{ 0x113E1, 0x113E2 }, { 0x11438, 0x1143F }, { 0x11442, 0x11444 }, { 0x11446, 0x11446 }, @@ -280,7 +286,8 @@ static const struct interval zero_width[] = { { 0x116AD, 0x116AD }, { 0x116B0, 0x116B5 }, { 0x116B7, 0x116B7 }, -{ 0x1171D, 0x1171F }, +{ 0x1171D, 0x1171D }, +{ 0x1171F, 0x1171F }, { 0x11722, 0x11725 }, { 0x11727, 0x1172B }, { 0x1182F, 0x11837 }, @@ -319,8 +326,11 @@ static const struct interval zero_width[] = { { 0x11F36, 0x11F3A }, { 0x11F40, 0x11F40 }, { 0x11F42, 0x11F42 }, +{ 0x11F5A, 0x11F5A }, { 0x13430, 0x13440 }, { 0x13447, 0x13455 }, +{ 0x1611E, 0x16129 }, +{ 0x1612D, 0x1612F }, { 0x16AF0, 0x16AF4 }, { 0x16B30, 0x16B36 }, { 0x16F4F, 0x16F4F }, @@ -351,6 +361,7 @@ static const struct interval zero_width[] = { { 0x1E2AE, 0x1E2AE }, { 0x1E2EC, 0x1E2EF }, { 0x1E4EC, 0x1E4EF }, +{ 0x1E5EE, 0x1E5EF }, { 0x1E8D0, 0x1E8D6 }, { 0x1E944, 0x1E94A }, { 0xE0001, 0xE0001 }, @@ -366,8 +377,10 @@ static const struct interval double_width[] = { { 0x23F3, 0x23F3 }, { 0x25FD, 0x25FE }, { 0x2614, 0x2615 }, +{ 0x2630, 0x2637 }, { 0x2648, 0x2653 }, { 0x267F, 0x267F }, +{ 0x268A, 0x268F }, { 0x2693, 0x2693 }, { 0x26A1, 0x26A1 }, { 0x26AA, 0x26AB }, @@ -401,11 +414,10 @@ static const struct interval double_width[] = { { 0x3099, 0x30FF }, { 0x3105, 0x312F }, { 0x3131, 0x318E }, -{ 0x3190, 0x31E3 }, +{ 0x3190, 0x31E5 }, { 0x31EF, 0x321E }, { 0x3220, 0x3247 }, -{ 0x3250, 0x4DBF }, -{ 0x4E00, 0xA48C }, +{ 0x3250, 0xA48C }, { 0xA490, 0xA4C6 }, { 0xA960, 0xA97C }, { 0xAC00, 0xD7A3 }, @@ -420,7 +432,7 @@ static const struct interval double_width[] = { { 0x16FF0, 0x16FF1 }, { 0x17000, 0x187F7 }, { 0x18800, 0x18CD5 }, -{ 0x18D00, 0x18D08 }, +{ 0x18CFF, 0x18D08 }, { 0x1AFF0, 0x1AFF3 }, { 0x1AFF5, 0x1AFFB }, { 0x1AFFD, 0x1AFFE }, @@ -430,6 +442,8 @@ static const struct interval double_width[] = { { 0x1B155, 0x1B155 }, { 0x1B164, 0x1B167 }, { 0x1B170, 0x1B2FB }, +{ 0x1D300, 0x1D356 }, +{ 0x1D360, 0x1D376 }, { 0x1F004, 0x1F004 }, { 0x1F0CF, 0x1F0CF }, { 0x1F18E, 0x1F18E }, @@ -470,11 +484,10 @@ static const struct interval double_width[] = { { 0x1F93C, 0x1F945 }, { 0x1F947, 0x1F9FF }, { 0x1FA70, 0x1FA7C }, -{ 0x1FA80, 0x1FA88 }, -{ 0x1FA90, 0x1FABD }, -{ 0x1FABF, 0x1FAC5 }, -{ 0x1FACE, 0x1FADB }, -{ 0x1FAE0, 0x1FAE8 }, +{ 0x1FA80, 0x1FA89 }, +{ 0x1FA8F, 0x1FAC6 }, +{ 0x1FACE, 0x1FADC }, +{ 0x1FADF, 0x1FAE9 }, { 0x1FAF0, 0x1FAF8 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } diff --git a/unpack-trees.c b/unpack-trees.c index 7dc884fafd..e10a9d1209 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -210,6 +210,7 @@ void clear_unpack_trees_porcelain(struct unpack_trees_options *opts) { strvec_clear(&opts->internal.msgs_to_free); memset(opts->internal.msgs, 0, sizeof(opts->internal.msgs)); + discard_index(&opts->internal.result); } static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce, @@ -807,6 +808,8 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names, if (!o->merge) BUG("We need cache-tree to do this optimization"); + if (nr_entries + pos > o->src_index->cache_nr) + return error(_("corrupted cache-tree has entries not present in index")); /* * Do what unpack_callback() and unpack_single_entry() normally @@ -2069,9 +2072,13 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options if (o->dst_index) { move_index_extensions(&o->internal.result, o->src_index); if (!ret) { - if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0)) - cache_tree_verify(the_repository, - &o->internal.result); + if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0) && + cache_tree_verify(the_repository, + &o->internal.result) < 0) { + ret = -1; + goto done; + } + if (!o->skip_cache_tree_update && !cache_tree_fully_valid(o->internal.result.cache_tree)) cache_tree_update(&o->internal.result, @@ -2082,6 +2089,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options o->internal.result.updated_workdir = 1; discard_index(o->dst_index); *o->dst_index = o->internal.result; + memset(&o->internal.result, 0, sizeof(o->internal.result)); } else { discard_index(&o->internal.result); } diff --git a/upload-pack.c b/upload-pack.c index 0052c6a4dc..43006c0614 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -166,6 +166,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data) object_array_clear(&data->extra_edge_obj); list_objects_filter_release(&data->filter_options); string_list_clear(&data->allowed_filters, 0); + string_list_clear(&data->uri_protocols, 0); free((char *)data->pack_objects_hook); } @@ -709,10 +710,13 @@ static int get_reachable_list(struct upload_pack_data *data, struct object *o; char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */ const unsigned hexsz = the_hash_algo->hexsz; + int ret; if (do_reachable_revlist(&cmd, &data->shallows, reachable, - data->allow_uor) < 0) - return -1; + data->allow_uor) < 0) { + ret = -1; + goto out; + } while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) { struct object_id oid; @@ -736,10 +740,16 @@ static int get_reachable_list(struct upload_pack_data *data, } close(cmd.out); - if (finish_command(&cmd)) - return -1; + if (finish_command(&cmd)) { + ret = -1; + goto out; + } - return 0; + ret = 0; + +out: + child_process_clear(&cmd); + return ret; } static int has_unreachable(struct object_array *src, enum allow_uor allow_uor) @@ -749,7 +759,7 @@ static int has_unreachable(struct object_array *src, enum allow_uor allow_uor) int i; if (do_reachable_revlist(&cmd, src, NULL, allow_uor) < 0) - return 1; + goto error; /* * The commits out of the rev-list are not ancestors of @@ -775,6 +785,7 @@ static int has_unreachable(struct object_array *src, enum allow_uor allow_uor) error: if (cmd.out >= 0) close(cmd.out); + child_process_clear(&cmd); return 1; } @@ -857,7 +868,7 @@ static void send_unshallow(struct upload_pack_data *data) } } -static int check_ref(const char *refname_full, const struct object_id *oid, +static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data); static void deepen(struct upload_pack_data *data, int depth) { @@ -1015,10 +1026,14 @@ static int process_deepen_not(const char *line, struct oidset *deepen_not, int * { const char *arg; if (skip_prefix(line, "deepen-not ", &arg)) { + int cnt; char *ref = NULL; struct object_id oid; - if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1) + cnt = expand_ref(the_repository, arg, strlen(arg), &oid, &ref); + if (cnt > 1) die("git upload-pack: ambiguous deepen-not: %s", line); + if (cnt < 1) + die("git upload-pack: deepen-not is not a ref: %s", line); oidset_insert(deepen_not, &oid); free(ref); *deepen_rev_list = 1; @@ -1208,7 +1223,7 @@ static int mark_our_ref(const char *refname, const char *refname_full, return 0; } -static int check_ref(const char *refname_full, const struct object_id *oid, +static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid, int flag UNUSED, void *cb_data) { const char *refname = strip_namespace(refname_full); @@ -1276,14 +1291,14 @@ static void write_v0_ref(struct upload_pack_data *data, return; } -static int send_ref(const char *refname, const struct object_id *oid, +static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { write_v0_ref(cb_data, refname, strip_namespace(refname), oid); return 0; } -static int find_symref(const char *refname, +static int find_symref(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flag, void *cb_data) { @@ -1802,7 +1817,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request) } else { /* * Request had 'want's but no 'have's so we can - * immedietly go to construct and send a pack. + * immediately go to construct and send a pack. */ state = FETCH_SEND_PACK; } @@ -350,18 +350,3 @@ void bug_fl(const char *file, int line, const char *fmt, ...) trace2_cmd_error_va(fmt, ap); va_end(ap); } - -#ifdef SUPPRESS_ANNOTATED_LEAKS -void unleak_memory(const void *ptr, size_t len) -{ - static struct suppressed_leak_root { - struct suppressed_leak_root *next; - char data[FLEX_ARRAY]; - } *suppressed_leaks; - struct suppressed_leak_root *root; - - FLEX_ALLOC_MEM(root, data, ptr, len); - root->next = suppressed_leaks; - suppressed_leaks = root; -} -#endif diff --git a/userdiff.c b/userdiff.c index c4ebb9ff73..d43d8360d1 100644 --- a/userdiff.c +++ b/userdiff.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "userdiff.h" @@ -399,8 +401,11 @@ static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t static int parse_funcname(struct userdiff_funcname *f, const char *k, const char *v, int cflags) { - if (git_config_string((char **) &f->pattern, k, v) < 0) + f->pattern = NULL; + FREE_AND_NULL(f->pattern_owned); + if (git_config_string(&f->pattern_owned, k, v) < 0) return -1; + f->pattern = f->pattern_owned; f->cflags = cflags; return 0; } @@ -444,20 +449,37 @@ int userdiff_config(const char *k, const char *v) return parse_funcname(&drv->funcname, k, v, REG_EXTENDED); if (!strcmp(type, "binary")) return parse_tristate(&drv->binary, k, v); - if (!strcmp(type, "command")) - return git_config_string((char **) &drv->external.cmd, k, v); + if (!strcmp(type, "command")) { + FREE_AND_NULL(drv->external.cmd); + return git_config_string(&drv->external.cmd, k, v); + } if (!strcmp(type, "trustexitcode")) { drv->external.trust_exit_code = git_config_bool(k, v); return 0; } - if (!strcmp(type, "textconv")) - return git_config_string((char **) &drv->textconv, k, v); + if (!strcmp(type, "textconv")) { + int ret; + FREE_AND_NULL(drv->textconv_owned); + ret = git_config_string(&drv->textconv_owned, k, v); + drv->textconv = drv->textconv_owned; + return ret; + } if (!strcmp(type, "cachetextconv")) return parse_bool(&drv->textconv_want_cache, k, v); - if (!strcmp(type, "wordregex")) - return git_config_string((char **) &drv->word_regex, k, v); - if (!strcmp(type, "algorithm")) - return git_config_string((char **) &drv->algorithm, k, v); + if (!strcmp(type, "wordregex")) { + int ret; + FREE_AND_NULL(drv->word_regex_owned); + ret = git_config_string(&drv->word_regex_owned, k, v); + drv->word_regex = drv->word_regex_owned; + return ret; + } + if (!strcmp(type, "algorithm")) { + int ret; + FREE_AND_NULL(drv->algorithm_owned); + ret = git_config_string(&drv->algorithm_owned, k, v); + drv->algorithm = drv->algorithm_owned; + return ret; + } return 0; } diff --git a/userdiff.h b/userdiff.h index 7565930337..827361b0bc 100644 --- a/userdiff.h +++ b/userdiff.h @@ -8,6 +8,7 @@ struct repository; struct userdiff_funcname { const char *pattern; + char *pattern_owned; int cflags; }; @@ -20,11 +21,14 @@ struct userdiff_driver { const char *name; struct external_diff external; const char *algorithm; + char *algorithm_owned; int binary; struct userdiff_funcname funcname; const char *word_regex; + char *word_regex_owned; const char *word_regex_multi_byte; const char *textconv; + char *textconv_owned; struct notes_cache *textconv_cache; int textconv_want_cache; }; @@ -33,8 +33,9 @@ char *reencode_string_len(const char *in, size_t insz, const char *in_encoding, size_t *outsz); #else -static inline char *reencode_string_len(const char *a, size_t b, - const char *c, const char *d, size_t *e) +static inline char *reencode_string_len(const char *a UNUSED, size_t b UNUSED, + const char *c UNUSED, + const char *d UNUSED, size_t *e) { if (e) *e = 0; return NULL; } #endif diff --git a/versioncmp.c b/versioncmp.c index 45e676cbca..e3b2a6e330 100644 --- a/versioncmp.c +++ b/versioncmp.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "strbuf.h" @@ -157,7 +157,7 @@ static int process(struct walker *walker, struct object *obj) else { if (obj->flags & COMPLETE) return 0; - walker->prefetch(walker, obj->oid.hash); + walker->prefetch(walker, &obj->oid); } object_list_insert(obj, process_queue_end); @@ -186,7 +186,7 @@ static int loop(struct walker *walker) * the queue because we needed to fetch it first. */ if (! (obj->flags & TO_SCAN)) { - if (walker->fetch(walker, obj->oid.hash)) { + if (walker->fetch(walker, &obj->oid)) { stop_progress(&progress); report_missing(obj); return -1; @@ -221,6 +221,7 @@ static int interpret_target(struct walker *walker, char *target, struct object_i } static int mark_complete(const char *path UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) @@ -289,7 +290,7 @@ int walker_fetch(struct walker *walker, int targets, char **target, if (write_ref) { transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - &err); + 0, &err); if (!transaction) { error("%s", err.buf); goto done; @@ -6,8 +6,8 @@ struct walker { void *data; int (*fetch_ref)(struct walker *, struct ref *ref); - void (*prefetch)(struct walker *, unsigned char *sha1); - int (*fetch)(struct walker *, unsigned char *sha1); + void (*prefetch)(struct walker *, const struct object_id *oid); + int (*fetch)(struct walker *, const struct object_id *oid); void (*cleanup)(struct walker *); int get_verbosely; int get_progress; diff --git a/worktree.c b/worktree.c index f3c4c8ec54..af68b24f9d 100644 --- a/worktree.c +++ b/worktree.c @@ -57,7 +57,7 @@ static void add_head_info(struct worktree *wt) static int is_current_worktree(struct worktree *wt) { - char *git_dir = absolute_pathdup(get_git_dir()); + char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository)); const char *wt_git_dir = get_worktree_git_dir(wt); int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir)); free(git_dir); @@ -72,7 +72,7 @@ static struct worktree *get_main_worktree(int skip_reading_head) struct worktree *worktree = NULL; struct strbuf worktree_path = STRBUF_INIT; - strbuf_add_real_path(&worktree_path, get_git_common_dir()); + strbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository)); strbuf_strip_suffix(&worktree_path, "/.git"); CALLOC_ARRAY(worktree, 1); @@ -110,6 +110,12 @@ struct worktree *get_linked_worktree(const char *id, strbuf_rtrim(&worktree_path); strbuf_strip_suffix(&worktree_path, "/.git"); + if (!is_absolute_path(worktree_path.buf)) { + strbuf_strip_suffix(&path, "gitdir"); + strbuf_addbuf(&path, &worktree_path); + strbuf_realpath_forgiving(&worktree_path, path.buf, 0); + } + CALLOC_ARRAY(worktree, 1); worktree->repo = the_repository; worktree->path = strbuf_detach(&worktree_path, NULL); @@ -143,7 +149,7 @@ static struct worktree **get_worktrees_internal(int skip_reading_head) list[counter++] = get_main_worktree(skip_reading_head); - strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); + strbuf_addf(&path, "%s/worktrees", repo_get_common_dir(the_repository)); dir = opendir(path.buf); strbuf_release(&path); if (dir) { @@ -171,9 +177,9 @@ struct worktree **get_worktrees(void) const char *get_worktree_git_dir(const struct worktree *wt) { if (!wt) - return get_git_dir(); + return repo_get_git_dir(the_repository); else if (!wt->id) - return get_git_common_dir(); + return repo_get_common_dir(the_repository); else return git_common_path("worktrees/%s", wt->id); } @@ -252,7 +258,7 @@ const char *worktree_lock_reason(struct worktree *wt) if (!wt->lock_reason_valid) { struct strbuf path = STRBUF_INIT; - strbuf_addstr(&path, worktree_git_path(wt, "locked")); + strbuf_addstr(&path, worktree_git_path(the_repository, wt, "locked")); if (file_exists(path.buf)) { struct strbuf lock_reason = STRBUF_INIT; if (strbuf_read_file(&lock_reason, path.buf, 0) < 0) @@ -370,21 +376,28 @@ done: return ret; } -void update_worktree_location(struct worktree *wt, const char *path_) +void update_worktree_location(struct worktree *wt, const char *path_, + int use_relative_paths) { struct strbuf path = STRBUF_INIT; + struct strbuf dotgit = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; if (is_main_worktree(wt)) BUG("can't relocate main worktree"); + strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); strbuf_realpath(&path, path_, 1); + strbuf_addf(&dotgit, "%s/.git", path.buf); if (fspathcmp(wt->path, path.buf)) { - write_file(git_common_path("worktrees/%s/gitdir", wt->id), - "%s/.git", path.buf); + write_worktree_linking_files(dotgit, gitdir, use_relative_paths); + free(wt->path); wt->path = strbuf_detach(&path, NULL); } strbuf_release(&path); + strbuf_release(&dotgit); + strbuf_release(&gitdir); } int is_worktree_being_rebased(const struct worktree *wt, @@ -546,7 +559,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data) refname.buf, RESOLVE_REF_READING, &oid, &flag)) - ret = fn(refname.buf, &oid, flag, cb_data); + ret = fn(refname.buf, NULL, &oid, flag, cb_data); if (ret) break; } @@ -560,42 +573,60 @@ int other_head_refs(each_ref_fn fn, void *cb_data) * pointing at <repo>/worktrees/<id>. */ static void repair_gitfile(struct worktree *wt, - worktree_repair_fn fn, void *cb_data) + worktree_repair_fn fn, void *cb_data, + int use_relative_paths) { struct strbuf dotgit = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; struct strbuf repo = STRBUF_INIT; - char *backlink; + struct strbuf backlink = STRBUF_INIT; + char *dotgit_contents = NULL; const char *repair = NULL; int err; /* missing worktree can't be repaired */ if (!file_exists(wt->path)) - return; + goto done; if (!is_directory(wt->path)) { fn(1, wt->path, _("not a directory"), cb_data); - return; + goto done; } strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); strbuf_addf(&dotgit, "%s/.git", wt->path); - backlink = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); + dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); + + if (dotgit_contents) { + if (is_absolute_path(dotgit_contents)) { + strbuf_addstr(&backlink, dotgit_contents); + } else { + strbuf_addf(&backlink, "%s/%s", wt->path, dotgit_contents); + strbuf_realpath_forgiving(&backlink, backlink.buf, 0); + } + } if (err == READ_GITFILE_ERR_NOT_A_FILE) fn(1, wt->path, _(".git is not a file"), cb_data); else if (err) repair = _(".git file broken"); - else if (fspathcmp(backlink, repo.buf)) + else if (fspathcmp(backlink.buf, repo.buf)) repair = _(".git file incorrect"); + else if (use_relative_paths == is_absolute_path(dotgit_contents)) + repair = _(".git file absolute/relative path mismatch"); if (repair) { fn(0, wt->path, repair, cb_data); - write_file(dotgit.buf, "gitdir: %s", repo.buf); + write_worktree_linking_files(dotgit, gitdir, use_relative_paths); } - free(backlink); +done: + free(dotgit_contents); strbuf_release(&repo); strbuf_release(&dotgit); + strbuf_release(&gitdir); + strbuf_release(&backlink); } static void repair_noop(int iserr UNUSED, @@ -606,7 +637,7 @@ static void repair_noop(int iserr UNUSED, /* nothing */ } -void repair_worktrees(worktree_repair_fn fn, void *cb_data) +void repair_worktrees(worktree_repair_fn fn, void *cb_data, int use_relative_paths) { struct worktree **worktrees = get_worktrees_internal(1); struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ @@ -614,7 +645,47 @@ void repair_worktrees(worktree_repair_fn fn, void *cb_data) if (!fn) fn = repair_noop; for (; *wt; wt++) - repair_gitfile(*wt, fn, cb_data); + repair_gitfile(*wt, fn, cb_data, use_relative_paths); + free_worktrees(worktrees); +} + +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; + + if (is_main_worktree(wt)) + goto done; + + strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + + if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0) + goto done; + + strbuf_rtrim(&dotgit); + is_relative_path = ! is_absolute_path(dotgit.buf); + if (is_relative_path) { + strbuf_insertf(&dotgit, 0, "%s/worktrees/%s/", old_path, wt->id); + strbuf_realpath_forgiving(&dotgit, dotgit.buf, 0); + } + + if (!file_exists(dotgit.buf)) + goto done; + + write_worktree_linking_files(dotgit, gitdir, is_relative_path); +done: + strbuf_release(&gitdir); + strbuf_release(&dotgit); +} + +void repair_worktrees_after_gitdir_move(const char *old_path) +{ + struct worktree **worktrees = get_worktrees_internal(1); + struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ + + for (; *wt; wt++) + repair_worktree_after_gitdir_move(*wt, old_path); free_worktrees(worktrees); } @@ -626,7 +697,7 @@ static int is_main_worktree_path(const char *path) strbuf_add_real_path(&target, path); strbuf_strip_suffix(&target, "/.git"); - strbuf_add_real_path(&maindir, get_git_common_dir()); + strbuf_add_real_path(&maindir, repo_get_common_dir(the_repository)); strbuf_strip_suffix(&maindir, "/.git"); cmp = fspathcmp(maindir.buf, target.buf); @@ -641,11 +712,12 @@ static int is_main_worktree_path(const char *path) * won't know which <repo>/worktrees/<id>/gitdir to repair. However, we may * be able to infer the gitdir by manually reading /path/to/worktree/.git, * extracting the <id>, and checking if <repo>/worktrees/<id> exists. + * + * Returns -1 on failure and strbuf.len on success. */ -static char *infer_backlink(const char *gitfile) +static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred) { struct strbuf actual = STRBUF_INIT; - struct strbuf inferred = STRBUF_INIT; const char *id; if (strbuf_read_file(&actual, gitfile, 0) < 0) @@ -658,17 +730,17 @@ static char *infer_backlink(const char *gitfile) id++; /* advance past '/' to point at <id> */ if (!*id) goto error; - strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id); - if (!is_directory(inferred.buf)) + strbuf_reset(inferred); + strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); + if (!is_directory(inferred->buf)) goto error; strbuf_release(&actual); - return strbuf_detach(&inferred, NULL); - + return inferred->len; error: strbuf_release(&actual); - strbuf_release(&inferred); - return NULL; + strbuf_reset(inferred); /* clear invalid path */ + return -1; } /* @@ -676,13 +748,15 @@ error: * the worktree's path. */ void repair_worktree_at_path(const char *path, - worktree_repair_fn fn, void *cb_data) + worktree_repair_fn fn, void *cb_data, + int use_relative_paths) { struct strbuf dotgit = STRBUF_INIT; - struct strbuf realdotgit = STRBUF_INIT; + struct strbuf backlink = STRBUF_INIT; + struct strbuf inferred_backlink = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; struct strbuf olddotgit = STRBUF_INIT; - char *backlink = NULL; + char *dotgit_contents = NULL; const char *repair = NULL; int err; @@ -693,112 +767,179 @@ void repair_worktree_at_path(const char *path, goto done; strbuf_addf(&dotgit, "%s/.git", path); - if (!strbuf_realpath(&realdotgit, dotgit.buf, 0)) { + if (!strbuf_realpath(&dotgit, dotgit.buf, 0)) { fn(1, path, _("not a valid path"), cb_data); goto done; } - backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); - if (err == READ_GITFILE_ERR_NOT_A_FILE) { - fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); + infer_backlink(dotgit.buf, &inferred_backlink); + strbuf_realpath_forgiving(&inferred_backlink, inferred_backlink.buf, 0); + dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); + if (dotgit_contents) { + if (is_absolute_path(dotgit_contents)) { + strbuf_addstr(&backlink, dotgit_contents); + } else { + strbuf_addbuf(&backlink, &dotgit); + strbuf_strip_suffix(&backlink, ".git"); + strbuf_addstr(&backlink, dotgit_contents); + strbuf_realpath_forgiving(&backlink, backlink.buf, 0); + } + } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { + fn(1, dotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { - if (!(backlink = infer_backlink(realdotgit.buf))) { - fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); + if (inferred_backlink.len) { + /* + * Worktree's .git file does not point at a repository + * but we found a .git/worktrees/<id> in this + * repository with the same <id> as recorded in the + * worktree's .git file so make the worktree point at + * the discovered .git/worktrees/<id>. + */ + strbuf_swap(&backlink, &inferred_backlink); + } else { + fn(1, dotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; } - } else if (err) { - fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); + } else { + fn(1, dotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; } - strbuf_addf(&gitdir, "%s/gitdir", backlink); + /* + * If we got this far, either the worktree's .git file pointed at a + * valid repository (i.e. read_gitfile_gently() returned success) or + * the .git file did not point at a repository but we were able to + * infer a suitable new value for the .git file by locating a + * .git/worktrees/<id> in *this* repository corresponding to the <id> + * recorded in the worktree's .git file. + * + * However, if, at this point, inferred_backlink is non-NULL (i.e. we + * found a suitable .git/worktrees/<id> in *this* repository) *and* the + * worktree's .git file points at a valid repository *and* those two + * paths differ, then that indicates that the user probably *copied* + * the main and linked worktrees to a new location as a unit rather + * than *moving* them. Thus, the copied worktree's .git file actually + * points at the .git/worktrees/<id> in the *original* repository, not + * in the "copy" repository. In this case, point the "copy" worktree's + * .git file at the "copy" repository. + */ + if (inferred_backlink.len && fspathcmp(backlink.buf, inferred_backlink.buf)) + strbuf_swap(&backlink, &inferred_backlink); + + strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) repair = _("gitdir unreadable"); + else if (use_relative_paths == is_absolute_path(olddotgit.buf)) + repair = _("gitdir absolute/relative path mismatch"); else { strbuf_rtrim(&olddotgit); - if (fspathcmp(olddotgit.buf, realdotgit.buf)) + if (!is_absolute_path(olddotgit.buf)) { + strbuf_insertf(&olddotgit, 0, "%s/", backlink.buf); + strbuf_realpath_forgiving(&olddotgit, olddotgit.buf, 0); + } + if (fspathcmp(olddotgit.buf, dotgit.buf)) repair = _("gitdir incorrect"); } if (repair) { fn(0, gitdir.buf, repair, cb_data); - write_file(gitdir.buf, "%s", realdotgit.buf); + write_worktree_linking_files(dotgit, gitdir, use_relative_paths); } done: - free(backlink); + free(dotgit_contents); strbuf_release(&olddotgit); + strbuf_release(&backlink); + strbuf_release(&inferred_backlink); strbuf_release(&gitdir); - strbuf_release(&realdotgit); strbuf_release(&dotgit); } int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire) { struct stat st; - char *path; + struct strbuf dotgit = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; + struct strbuf repo = STRBUF_INIT; + struct strbuf file = STRBUF_INIT; + char *path = NULL; + int rc = 0; int fd; size_t len; ssize_t read_result; *wtpath = NULL; - if (!is_directory(git_path("worktrees/%s", id))) { + strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); + if (!is_directory(repo.buf)) { strbuf_addstr(reason, _("not a valid directory")); - return 1; + rc = 1; + goto done; } - if (file_exists(git_path("worktrees/%s/locked", id))) - return 0; - if (stat(git_path("worktrees/%s/gitdir", id), &st)) { + strbuf_addf(&file, "%s/locked", repo.buf); + if (file_exists(file.buf)) { + goto done; + } + if (stat(gitdir.buf, &st)) { strbuf_addstr(reason, _("gitdir file does not exist")); - return 1; + rc = 1; + goto done; } - fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY); + fd = open(gitdir.buf, O_RDONLY); if (fd < 0) { strbuf_addf(reason, _("unable to read gitdir file (%s)"), strerror(errno)); - return 1; + rc = 1; + goto done; } len = xsize_t(st.st_size); path = xmallocz(len); read_result = read_in_full(fd, path, len); + close(fd); if (read_result < 0) { strbuf_addf(reason, _("unable to read gitdir file (%s)"), strerror(errno)); - close(fd); - free(path); - return 1; - } - close(fd); - - if (read_result != len) { + rc = 1; + goto done; + } else if (read_result != len) { strbuf_addf(reason, _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"), (uintmax_t)len, (uintmax_t)read_result); - free(path); - return 1; + rc = 1; + goto done; } while (len && (path[len - 1] == '\n' || path[len - 1] == '\r')) len--; if (!len) { strbuf_addstr(reason, _("invalid gitdir file")); - free(path); - return 1; + rc = 1; + goto done; } path[len] = '\0'; - if (!file_exists(path)) { - if (stat(git_path("worktrees/%s/index", id), &st) || - st.st_mtime <= expire) { + if (is_absolute_path(path)) { + strbuf_addstr(&dotgit, path); + } else { + strbuf_addf(&dotgit, "%s/%s", repo.buf, path); + strbuf_realpath_forgiving(&dotgit, dotgit.buf, 0); + } + if (!file_exists(dotgit.buf)) { + strbuf_reset(&file); + strbuf_addf(&file, "%s/index", repo.buf); + if (stat(file.buf, &st) || st.st_mtime <= expire) { strbuf_addstr(reason, _("gitdir file points to non-existent location")); - free(path); - return 1; - } else { - *wtpath = path; - return 0; + rc = 1; + goto done; } } - *wtpath = path; - return 0; + *wtpath = strbuf_detach(&dotgit, NULL); +done: + free(path); + strbuf_release(&dotgit); + strbuf_release(&gitdir); + strbuf_release(&repo); + strbuf_release(&file); + return rc; } static int move_config_setting(const char *key, const char *value, @@ -872,3 +1013,38 @@ cleanup: free(main_worktree_file); return res; } + +void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir, + int use_relative_paths) +{ + struct strbuf path = STRBUF_INIT; + struct strbuf repo = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + + strbuf_addbuf(&path, &dotgit); + strbuf_strip_suffix(&path, "/.git"); + strbuf_realpath(&path, path.buf, 1); + strbuf_addbuf(&repo, &gitdir); + strbuf_strip_suffix(&repo, "/gitdir"); + strbuf_realpath(&repo, repo.buf, 1); + + if (use_relative_paths && !the_repository->repository_format_relative_worktrees) { + if (upgrade_repository_format(1) < 0) + die(_("unable to upgrade repository format to support relative worktrees")); + if (git_config_set_gently("extensions.relativeWorktrees", "true")) + die(_("unable to set extensions.relativeWorktrees setting")); + the_repository->repository_format_relative_worktrees = 1; + } + + if (use_relative_paths) { + write_file(gitdir.buf, "%s/.git", relative_path(path.buf, repo.buf, &tmp)); + write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp)); + } else { + write_file(gitdir.buf, "%s/.git", path.buf); + write_file(dotgit.buf, "gitdir: %s", repo.buf); + } + + strbuf_release(&path); + strbuf_release(&repo); + strbuf_release(&tmp); +} diff --git a/worktree.h b/worktree.h index 11279d0c8f..38145df80f 100644 --- a/worktree.h +++ b/worktree.h @@ -117,8 +117,8 @@ int validate_worktree(const struct worktree *wt, /* * Update worktrees/xxx/gitdir with the new path. */ -void update_worktree_location(struct worktree *wt, - const char *path_); +void update_worktree_location(struct worktree *wt, const char *path_, + int use_relative_paths); typedef void (* worktree_repair_fn)(int iserr, const char *path, const char *msg, void *cb_data); @@ -129,7 +129,17 @@ typedef void (* worktree_repair_fn)(int iserr, const char *path, * function, if non-NULL, is called with the path of the worktree and a * description of the repair or error, along with the callback user-data. */ -void repair_worktrees(worktree_repair_fn, void *cb_data); +void repair_worktrees(worktree_repair_fn, void *cb_data, int use_relative_paths); + +/* + * Repair the linked worktrees after the gitdir has been moved. + */ +void repair_worktrees_after_gitdir_move(const char *old_path); + +/* + * Repair the linked worktree after the gitdir has been moved. + */ +void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path); /* * Repair administrative files corresponding to the worktree at the given path. @@ -141,7 +151,8 @@ void repair_worktrees(worktree_repair_fn, void *cb_data); * worktree and a description of the repair or error, along with the callback * user-data. */ -void repair_worktree_at_path(const char *, worktree_repair_fn, void *cb_data); +void repair_worktree_at_path(const char *, worktree_repair_fn, + void *cb_data, int use_relative_paths); /* * Free up the memory for a worktree. @@ -205,4 +216,17 @@ void strbuf_worktree_ref(const struct worktree *wt, */ int init_worktree_config(struct repository *r); +/** + * Write the .git file and gitdir file that links the worktree to the repository. + * + * The `dotgit` parameter is the path to the worktree's .git file, and `gitdir` + * is the path to the repository's `gitdir` file. + * + * Example + * dotgit: "/path/to/foo/.git" + * gitdir: "/path/to/repo/worktrees/foo/gitdir" + */ +void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir, + int use_relative_paths); + #endif @@ -140,4 +140,22 @@ int csprng_bytes(void *buf, size_t len); */ uint32_t git_rand(void); +/* Provide log2 of the given `size_t`. */ +static inline unsigned log2u(uintmax_t sz) +{ + unsigned l = 0; + + /* + * Technically this isn't required, but it helps the compiler optimize + * this to a `bsr` instruction. + */ + if (!sz) + return 0; + + for (; sz; sz >>= 1) + l++; + + return l - 1; +} + #endif /* WRAPPER_H */ diff --git a/wt-status.c b/wt-status.c index b778eef989..6a8c05d1cf 100644 --- a/wt-status.c +++ b/wt-status.c @@ -16,6 +16,7 @@ #include "revision.h" #include "diffcore.h" #include "quote.h" +#include "repository.h" #include "run-command.h" #include "strvec.h" #include "remote.h" @@ -152,7 +153,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s) "HEAD", 0, NULL, NULL); s->reference = "HEAD"; s->fp = stdout; - s->index_file = get_index_file(); + s->index_file = repo_get_index_file(the_repository); s->change.strdup_strings = 1; s->untracked.strdup_strings = 1; s->ignored.strdup_strings = 1; @@ -716,6 +717,7 @@ static int add_file_to_list(const struct object_id *oid, static void wt_status_collect_changes_initial(struct wt_status *s) { struct index_state *istate = s->repo->index; + struct strbuf base = STRBUF_INIT; int i; for (i = 0; i < istate->cache_nr; i++) { @@ -734,7 +736,6 @@ static void wt_status_collect_changes_initial(struct wt_status *s) * expanding the trees to find the elements that are new in this * tree and marking them with DIFF_STATUS_ADDED. */ - struct strbuf base = STRBUF_INIT; struct pathspec ps = { 0 }; struct tree *tree = lookup_tree(istate->repo, &ce->oid); @@ -742,9 +743,11 @@ static void wt_status_collect_changes_initial(struct wt_status *s) ps.has_wildcard = 1; ps.max_depth = -1; + strbuf_reset(&base); strbuf_add(&base, ce->name, ce->ce_namelen); read_tree_at(istate->repo, tree, &base, 0, &ps, add_file_to_list, s); + continue; } @@ -771,6 +774,8 @@ static void wt_status_collect_changes_initial(struct wt_status *s) s->committable = 1; } } + + strbuf_release(&base); } static void wt_status_collect_untracked(struct wt_status *s) @@ -1618,7 +1623,7 @@ static char *get_branch(const struct worktree *wt, const char *path) struct object_id oid; const char *branch_name; - if (strbuf_read_file(&sb, worktree_git_path(wt, "%s", path), 0) <= 0) + if (strbuf_read_file(&sb, worktree_git_path(the_repository, wt, "%s", path), 0) <= 0) goto got_nothing; while (sb.len && sb.buf[sb.len - 1] == '\n') @@ -1716,18 +1721,18 @@ int wt_status_check_rebase(const struct worktree *wt, { struct stat st; - if (!stat(worktree_git_path(wt, "rebase-apply"), &st)) { - if (!stat(worktree_git_path(wt, "rebase-apply/applying"), &st)) { + if (!stat(worktree_git_path(the_repository, wt, "rebase-apply"), &st)) { + if (!stat(worktree_git_path(the_repository, wt, "rebase-apply/applying"), &st)) { state->am_in_progress = 1; - if (!stat(worktree_git_path(wt, "rebase-apply/patch"), &st) && !st.st_size) + if (!stat(worktree_git_path(the_repository, wt, "rebase-apply/patch"), &st) && !st.st_size) state->am_empty_patch = 1; } else { state->rebase_in_progress = 1; state->branch = get_branch(wt, "rebase-apply/head-name"); state->onto = get_branch(wt, "rebase-apply/onto"); } - } else if (!stat(worktree_git_path(wt, "rebase-merge"), &st)) { - if (!stat(worktree_git_path(wt, "rebase-merge/interactive"), &st)) + } else if (!stat(worktree_git_path(the_repository, wt, "rebase-merge"), &st)) { + if (!stat(worktree_git_path(the_repository, wt, "rebase-merge/interactive"), &st)) state->rebase_interactive_in_progress = 1; else state->rebase_in_progress = 1; @@ -1743,7 +1748,7 @@ int wt_status_check_bisect(const struct worktree *wt, { struct stat st; - if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) { + if (!stat(worktree_git_path(the_repository, wt, "BISECT_LOG"), &st)) { state->bisect_in_progress = 1; state->bisecting_from = get_branch(wt, "BISECT_START"); return 1; @@ -2595,7 +2600,7 @@ int has_unstaged_changes(struct repository *r, int ignore_submodules) rev_info.diffopt.flags.quick = 1; diff_setup_done(&rev_info.diffopt); run_diff_files(&rev_info, 0); - result = diff_result_code(&rev_info.diffopt); + result = diff_result_code(&rev_info); release_revisions(&rev_info); return result; } @@ -2629,7 +2634,7 @@ int has_uncommitted_changes(struct repository *r, diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, DIFF_INDEX_CACHED); - result = diff_result_code(&rev_info.diffopt); + result = diff_result_code(&rev_info); release_revisions(&rev_info); return result; } |
